Adding Prettier and fixing up eslint version 81/36981/3
authorEinav Weiss Keidar <einavw@amdocs.com>
Tue, 20 Mar 2018 12:45:40 +0000 (14:45 +0200)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Tue, 20 Mar 2018 13:52:31 +0000 (13:52 +0000)
Issue-ID: SDC-1094
Change-Id: Ie83ad95a03899345dd90235daf0323cbe3bc6afd
Signed-off-by: Einav Weiss Keidar <einavw@amdocs.com>
414 files changed:
dox-sequence-diagram-ui/.prettierrc [new file with mode: 0644]
dox-sequence-diagram-ui/eslintrc.json
dox-sequence-diagram-ui/package.json
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/Sequencer.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/common/Common.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/common/Logger.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/common/Options.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/application/Application.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/diagram/Diagram.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/diagram/components/popup/Popup.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/dialog/Dialog.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/Editor.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/Designer.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/actions/Actions.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/lifeline/Lifeline.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/lifeline/LifelineNew.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/lifeline/Lifelines.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/message/Message.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/message/MessageNew.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/message/Messages.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/designer/components/metadata/Metadata.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/source/Source.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/editor/components/toolbar/Toolbar.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/export/Export.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/icons/Icon.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/components/overlay/Overlay.jsx
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/model/Metamodel.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/model/Metamodels.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/model/Model.js
dox-sequence-diagram-ui/src/main/webapp/lib/ecomp/asdc/sequencer/model/demo/scenarios/Scenarios.js
dox-sequence-diagram-ui/src/main/webapp/lib/main.jsx
dox-sequence-diagram-ui/yarn.lock
openecomp-ui/.eslintrc
openecomp-ui/.prettierrc [new file with mode: 0644]
openecomp-ui/package.json
openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx
openecomp-ui/src/nfvo-components/accordion/Accordion.jsx
openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx
openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx
openecomp-ui/src/nfvo-components/fileupload/DraggableUploadFileBox.jsx
openecomp-ui/src/nfvo-components/grid/GridItem.jsx
openecomp-ui/src/nfvo-components/grid/GridSection.jsx
openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx
openecomp-ui/src/nfvo-components/input/SelectInput.jsx
openecomp-ui/src/nfvo-components/input/ToggleInput.jsx
openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx
openecomp-ui/src/nfvo-components/input/validation/Form.jsx
openecomp-ui/src/nfvo-components/input/validation/Input.jsx
openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx
openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx
openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
openecomp-ui/src/nfvo-components/listEditor/ListEditorItemViewField.jsx
openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx
openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js
openecomp-ui/src/nfvo-components/loader/Loader.jsx
openecomp-ui/src/nfvo-components/loader/LoaderConstants.js
openecomp-ui/src/nfvo-components/loader/LoaderReducer.js
openecomp-ui/src/nfvo-components/modal/GlobalModal.js
openecomp-ui/src/nfvo-components/modal/GlobalModalConstants.js
openecomp-ui/src/nfvo-components/modal/GlobalModalReducer.js
openecomp-ui/src/nfvo-components/modal/Modal.jsx
openecomp-ui/src/nfvo-components/overlay/Overlay.jsx
openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx
openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx
openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
openecomp-ui/src/nfvo-components/panel/versionController/components/ActionButtons.jsx
openecomp-ui/src/nfvo-components/panel/versionController/components/CommitCommentModal.jsx
openecomp-ui/src/nfvo-components/panel/versionController/components/Permissions.jsx
openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx
openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
openecomp-ui/src/nfvo-components/table/SelectActionTableCell.jsx
openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
openecomp-ui/src/nfvo-components/tree/Tree.jsx
openecomp-ui/src/nfvo-components/tree/Tree.stories.js
openecomp-ui/src/nfvo-utils/DirectedGraph.js
openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js
openecomp-ui/src/nfvo-utils/KeyMirror.js
openecomp-ui/src/nfvo-utils/RestAPIUtil.js
openecomp-ui/src/nfvo-utils/ShowFileSaveDialog.js
openecomp-ui/src/nfvo-utils/UUID.js
openecomp-ui/src/nfvo-utils/Validator.js
openecomp-ui/src/nfvo-utils/WebSocketUtil.js
openecomp-ui/src/nfvo-utils/getValue.js
openecomp-ui/src/nfvo-utils/i18n/i18n.js
openecomp-ui/src/nfvo-utils/i18n/i18n.stories.js
openecomp-ui/src/nfvo-utils/json/JSONPointer.js
openecomp-ui/src/nfvo-utils/json/JSONSchema.js
openecomp-ui/src/nfvo-utils/sortByStringProperty.js
openecomp-ui/src/sdc-app/AppStore.js
openecomp-ui/src/sdc-app/Application.jsx
openecomp-ui/src/sdc-app/ModulesOptions.jsx
openecomp-ui/src/sdc-app/Reducers.js
openecomp-ui/src/sdc-app/common/activity-log/ActivityLog.js
openecomp-ui/src/sdc-app/common/activity-log/ActivityLogActionHelper.js
openecomp-ui/src/sdc-app/common/activity-log/ActivityLogConstants.js
openecomp-ui/src/sdc-app/common/activity-log/ActivityLogReducer.js
openecomp-ui/src/sdc-app/common/activity-log/ActivityLogView.jsx
openecomp-ui/src/sdc-app/common/activity-log/LogixUtil.jsx
openecomp-ui/src/sdc-app/common/helpers/ItemsHelper.js
openecomp-ui/src/sdc-app/common/helpers/ScreensHelper.js
openecomp-ui/src/sdc-app/common/helpers/ValidationHelper.js
openecomp-ui/src/sdc-app/common/merge/MergeEditor.js
openecomp-ui/src/sdc-app/common/merge/MergeEditorActionHelper.js
openecomp-ui/src/sdc-app/common/merge/MergeEditorConstants.js
openecomp-ui/src/sdc-app/common/merge/MergeEditorReducer.js
openecomp-ui/src/sdc-app/common/merge/MergeEditorView.jsx
openecomp-ui/src/sdc-app/common/modal/ModalContentMapper.js
openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducer.js
openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducerConstants.js
openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
openecomp-ui/src/sdc-app/common/reducers/PlainDataReducerConstants.js
openecomp-ui/src/sdc-app/config/Configuration.js
openecomp-ui/src/sdc-app/features/FeaturesActionHelper.js
openecomp-ui/src/sdc-app/features/FeaturesConstants.js
openecomp-ui/src/sdc-app/features/FeaturesReducer.js
openecomp-ui/src/sdc-app/features/featureToggle.js
openecomp-ui/src/sdc-app/features/restToggle.js
openecomp-ui/src/sdc-app/flows/FlowsActions.js
openecomp-ui/src/sdc-app/flows/FlowsConstants.js
openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js
openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx
openecomp-ui/src/sdc-app/flows/FlowsListEditor.js
openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx
openecomp-ui/src/sdc-app/flows/FlowsListReducer.js
openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx
openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js
openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx
openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx
openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js
openecomp-ui/src/sdc-app/heatValidation.app.jsx
openecomp-ui/src/sdc-app/heatvalidation/Attachments.js
openecomp-ui/src/sdc-app/heatvalidation/HeatSetup.js
openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx
openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js
openecomp-ui/src/sdc-app/onboarding/GridStyling.stories.js
openecomp-ui/src/sdc-app/onboarding/Onboarding.js
openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js
openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js
openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js
openecomp-ui/src/sdc-app/onboarding/OnboardingView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/ArchivedLicenseModelListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelValidations.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsLimits.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsLimits.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/Limits.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitsServer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js
openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/filter/Filter.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterConstants.js
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterReducer.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx
openecomp-ui/src/sdc-app/onboarding/permissions/PermissionsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/permissions/PermissionsConstants.js
openecomp-ui/src/sdc-app/onboarding/permissions/PermissionsManager.js
openecomp-ui/src/sdc-app/onboarding/permissions/PermissionsManager.jsx
openecomp-ui/src/sdc-app/onboarding/permissions/PermissionsReducer.js
openecomp-ui/src/sdc-app/onboarding/revisions/Revisions.js
openecomp-ui/src/sdc-app/onboarding/revisions/RevisionsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/revisions/RevisionsConstants.js
openecomp-ui/src/sdc-app/onboarding/revisions/RevisionsReducer.js
openecomp-ui/src/sdc-app/onboarding/revisions/RevisionsView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/ArchivedSoftwareProductReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/ImageValidations.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeployment.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx
openecomp-ui/src/sdc-app/onboarding/userNotifications/NotificationsReducer.js
openecomp-ui/src/sdc-app/onboarding/userNotifications/NotificationsView.jsx
openecomp-ui/src/sdc-app/onboarding/userNotifications/UserNotifications.jsx
openecomp-ui/src/sdc-app/onboarding/userNotifications/UserNotificationsActionHelper.js
openecomp-ui/src/sdc-app/onboarding/userNotifications/UserNotificationsConstants.js
openecomp-ui/src/sdc-app/onboarding/users/UsersActionHelper.js
openecomp-ui/src/sdc-app/onboarding/users/UsersConstants.js
openecomp-ui/src/sdc-app/onboarding/users/UsersReducers.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.jsx
openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageConstants.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageReducer.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/components/PermissionsView.jsx
openecomp-ui/src/sdc-app/onboarding/versionsPage/components/VersionList.jsx
openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx
openecomp-ui/src/sdc-app/sdc.app.jsx
openecomp-ui/webpack.common.js
openecomp-ui/webpack.production.js
openecomp-ui/yarn.lock

diff --git a/dox-sequence-diagram-ui/.prettierrc b/dox-sequence-diagram-ui/.prettierrc
new file mode 100644 (file)
index 0000000..40321d4
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "singleQuote": true,
+  "jsxBracketSameLine": true,
+  "tabWidth": 4
+}
\ No newline at end of file
index b2a3f24..01b65f3 100644 (file)
 {
-  "parserOptions": {
-    "ecmaVersion": 6,
-    "sourceType": "module",
-    "ecmaFeatures": {
-      "jsx": true
+    "parser": "babel-eslint",
+    "parserOptions": {
+        "ecmaVersion": 6,
+        "sourceType": "module",
+        "ecmaFeatures": {
+            "jsx": true,
+            "classes": true,
+            "modules": true,
+            "experimentalDecorators": true
+        }
+    },
+    "env": {
+        "es6": true,
+        "jquery": true,
+        "node": true,
+        "jest": true
+    },
+    "plugins": ["react", "import", "prettier"],
+    "extends": ["prettier"],
+    "globals": {
+        "Event": true,
+        "window": true,
+        "navigator": true,
+        "System": true,
+        "document": true,
+        "localStorage": true,
+        "sessionStorage": true,
+        "Image": true,
+        "requestAnimationFrame": true,
+        "cancelAnimationFrame": true,
+        "DEBUG": true,
+        "SVGElement": true,
+        "FormData": true,
+        "DEV": true,
+        "Blob": true,
+        "XMLHttpRequest": true,
+        "WebSocket": true,
+        "URL": true,
+        "PunchOutRegistry": true,
+        "it": true,
+        "describe": true
+    },
+    "rules": {
+        "prettier/prettier": [
+            "error",
+            {
+                "singleQuote": true,
+                "jsxBracketSameLine": true,
+                "tabWidth": 4
+            }
+        ],
+        "linebreak-style": 0,
+        "no-unused-vars": 2,
+        "no-bitwise": 0,
+        "no-eq-null": 2,
+        "eqeqeq": 2,
+        "no-unused-expressions": 2,
+        "no-use-before-define": 2,
+        "new-cap": [
+            2,
+            {
+                "capIsNewExceptions": ["DataTable", "V"]
+            }
+        ],
+        "no-caller": 2,
+        "no-empty": 2,
+        "no-undef": 2,
+        "quotes": [2, "single", "avoid-escape"],
+        "no-plusplus": 0,
+        "no-cond-assign": [2, "except-parens"],
+        "no-invalid-this": 0,
+        "dot-notation": 0,
+        "camelcase": [
+            2,
+            {
+                "properties": "never"
+            }
+        ],
+        "curly": 2,
+        "semi": [2, "always"],
+        "import/default": 0,
+        "import/no-unresolved": 0,
+        "import/no-named-as-default": 2,
+        "import/no-duplicates": 0,
+        "import/imports-first": 2,
+        "import/export": 2,
+        "react/display-name": 0,
+        "react/forbid-prop-types": 0,
+        "react/jsx-boolean-value": 0,
+        "react/jsx-no-duplicate-props": 1,
+        "react/jsx-no-literals": 0,
+        "react/jsx-no-undef": 1,
+        "react/jsx-sort-prop-types": 0,
+        "react/jsx-sort-props": 0,
+        "react/jsx-uses-react": 1,
+        "react/jsx-uses-vars": 1,
+        "react/no-danger": 1,
+        "react/no-did-mount-set-state": 2,
+        "react/no-did-update-set-state": 2,
+        "react/no-direct-mutation-state": 1,
+        "react/no-multi-comp": 0,
+        "react/no-set-state": 0,
+        "react/no-unknown-property": 1,
+        "react/prop-types": 0,
+        "react/react-in-jsx-scope": 1,
+        "react/self-closing-comp": 1,
+        "react/sort-comp": 0
     }
-  },
-  "env": {
-    "browser": true
-  },
-  "plugins": [
-    "react"
-  ],
-  "extends": [
-    "airbnb"
-  ],
-  "rules": {
-    "padded-blocks": 0,
-    "max-len": ["error", 160, 4],
-    "no-underscore-dangle": 0,
-    "global-require": 0,
-    "react/sort-comp": 0,
-    "new-cap": 0
-  },
-  "settings": {
-    "react": {
-      "pragma": "React",
-      "version": "0.14.8"
-    }
-  }
 }
index aa9976e..dbbfd84 100644 (file)
@@ -1,57 +1,59 @@
 {
-  "name": "dox-sequence-diagram-ui",
-  "version": "1.0.0",
-  "description": "",
-  "main": "dist/index.js",
-  "scripts": {
-    "build": "webpack",
-    "start": "webpack-dev-server",
-    "lint": "eslint . --ext .js --ext .jsx --cache"
-  },
-  "author": "ONAP",
-  "license": "SEE LICENSE IN LICENSE",
-  "dependencies": {
-    "d3": "^4.10.0",
-    "lodash": "^4.12.0",
-    "prop-types": "^15.6.0",
-    "react": "^15.6.2",
-    "react-dnd": "^2.5.4",
-    "react-dnd-html5-backend": "^2.5.4",
-    "react-dom": "^15.6.2",
-    "react-redux": "^5.0.6",
-    "react-select": "1.2.1",
-    "redux": "^3.7.2"
-  },
-  "devDependencies": {
-    "babel-core": "^6.26.0",
-    "babel-eslint": "^8.2.1",
-    "babel-loader": "^7.1.2",
-    "babel-plugin-lodash": "^3.3.2",
-    "babel-preset-env": "^1.6.1",
-    "babel-preset-react": "^6.5.0",
-    "copy": "^0.2.0",
-    "css-loader": "^0.28.7",
-    "eslint": "^2.10.2",
-    "eslint-config-airbnb": "^9.0.1",
-    "eslint-loader": "^1.3.0",
-    "eslint-plugin-import": "^1.8.0",
-    "eslint-plugin-jsx-a11y": "^1.2.2",
-    "eslint-plugin-react": "^5.1.1",
-    "file-loader": "^1.1.6",
-    "node-sass": "^4.7.2",
-    "path": "^0.12.7",
-    "raw-loader": "^0.5.1",
-    "redux-devtools": "^3.3.1",
-    "sass-loader": "^6.0.6",
-    "style-loader": "^0.19.1",
-    "svg-sprite-loader": "0.0.19",
-    "url-loader": "^0.6.2",
-    "webpack": "^2.2.1",
-    "webpack-dev-server": "^2.4.2"
-  },
-  "engines": {
-    "node": ">=8.0.0",
-    "npm": ">=5.0.0",
-    "yarn": "^1.3.2"
-  }
-}
\ No newline at end of file
+    "name": "dox-sequence-diagram-ui",
+    "version": "1.0.0",
+    "description": "",
+    "main": "dist/index.js",
+    "scripts": {
+        "build": "webpack",
+        "start": "webpack-dev-server",
+        "lint": "eslint . --ext .js --ext .jsx --cache -c eslintrc.json",
+        "lint-fix": "eslint --fix -c eslintrc.json --ext .js --ext .jsx src"
+    },
+    "author": "ONAP",
+    "license": "SEE LICENSE IN LICENSE",
+    "dependencies": {
+        "d3": "^4.10.0",
+        "lodash": "^4.12.0",
+        "prop-types": "^15.6.0",
+        "react": "^15.6.2",
+        "react-dnd": "^2.5.4",
+        "react-dnd-html5-backend": "^2.5.4",
+        "react-dom": "^15.6.2",
+        "react-redux": "^5.0.6",
+        "react-select": "1.2.1",
+        "redux": "^3.7.2"
+    },
+    "devDependencies": {
+        "babel-core": "^6.26.0",
+        "babel-eslint": "^8.2.1",
+        "babel-loader": "^7.1.2",
+        "babel-plugin-lodash": "^3.3.2",
+        "babel-preset-env": "^1.6.1",
+        "babel-preset-react": "^6.5.0",
+        "copy": "^0.2.0",
+        "css-loader": "^0.28.7",
+        "eslint": "^4.18.1",
+        "eslint-config-prettier": "^2.9.0",
+        "eslint-loader": "^1.9.0",
+        "eslint-plugin-import": "^2.9.0",
+        "eslint-plugin-prettier": "^2.6.0",
+        "eslint-plugin-react": "^7.7.0",
+        "file-loader": "^1.1.6",
+        "node-sass": "^4.7.2",
+        "path": "^0.12.7",
+        "prettier": "^1.10.2",
+        "raw-loader": "^0.5.1",
+        "redux-devtools": "^3.3.1",
+        "sass-loader": "^6.0.6",
+        "style-loader": "^0.19.1",
+        "svg-sprite-loader": "0.0.19",
+        "url-loader": "^0.6.2",
+        "webpack": "^2.2.1",
+        "webpack-dev-server": "^2.4.2"
+    },
+    "engines": {
+        "node": ">=8.0.0",
+        "npm": ">=5.0.0",
+        "yarn": "^1.3.2"
+    }
+}
index fc2bfbc..c0e9483 100644 (file)
@@ -28,176 +28,177 @@ import '../../../../res/sdc-sequencer.scss';
  * ASDC Sequencer entry point.
  */
 class Sequencer extends React.Component {
+    // //////////////////////////////////////////////////////////////////////////////////////////////
 
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  constructor(props, context) {
-    super(props, context);
-
-
-    this.setMetamodel.bind(this);
-    this.setModel.bind(this);
-    this.getModel.bind(this);
-    this.getMetamodel.bind(this);
-    this.getSVG.bind(this);
-    this.getDemoScenarios.bind(this);
-    this.newModel.bind(this);
-
-    // Parse options.
-
-    this.options = new Options(props.options);
-
-    // Default scenarios.
-
-    const scenarios = this.getDemoScenarios();
-    this.setMetamodel(scenarios.getMetamodels());
-
-    // this.setModel(scenarios.getBlank());
-    this.setModel(scenarios.getDimensions());
-    // this.setModel(scenarios.getECOMP());
-
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Optionally save known metamodels so that subsequent loading and unloading
-   * of models needn't include the corresponding metamodel.
-   * @param metamodels array of conformant metamodel JSON definitions.
-   * @return this.
-   */
-  setMetamodel(metamodels) {
-    Common.assertType(metamodels, 'Array');
-    this.metamodels = new Metamodels(metamodels);
-    return this;
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Set current diagram.
-   * @param modelJSON JSON diagram spec.
-   * @param metamodelIdOrDefinition optional metamodel definition or reference. Defaults to
-   * the model's metadata @ref, or the default (permissive) metamodel.
-   * @return this.
-   */
-  setModel(modelJSON, metamodelIdOrDefinition) {
-    Common.assertType(modelJSON, 'Object');
-    const ref = (modelJSON.metadata) ? modelJSON.metadata.ref : undefined;
-    const metamodel = this.getMetamodel(metamodelIdOrDefinition || ref);
-    Common.assertInstanceOf(metamodel, Metamodel);
-    this.model = new Model(modelJSON, metamodel);
-    if (this.application) {
-      this.application.setModel(this.model);
+    constructor(props, context) {
+        super(props, context);
+
+        this.setMetamodel.bind(this);
+        this.setModel.bind(this);
+        this.getModel.bind(this);
+        this.getMetamodel.bind(this);
+        this.getSVG.bind(this);
+        this.getDemoScenarios.bind(this);
+        this.newModel.bind(this);
+
+        // Parse options.
+
+        this.options = new Options(props.options);
+
+        // Default scenarios.
+
+        const scenarios = this.getDemoScenarios();
+        this.setMetamodel(scenarios.getMetamodels());
+
+        // this.setModel(scenarios.getBlank());
+        this.setModel(scenarios.getDimensions());
+        // this.setModel(scenarios.getECOMP());
     }
-    return this;
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get current diagram state. At any given instant the diagram might not make *sense*
-   * but it should always be syntactically valid.
-   * @return current Model.
-   */
-  getModel() {
-
-    if (this.application) {
-      const model = this.application.getModel();
-      if (model) {
-        return model.unwrap();
-      }
+
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Optionally save known metamodels so that subsequent loading and unloading
+     * of models needn't include the corresponding metamodel.
+     * @param metamodels array of conformant metamodel JSON definitions.
+     * @return this.
+     */
+    setMetamodel(metamodels) {
+        Common.assertType(metamodels, 'Array');
+        this.metamodels = new Metamodels(metamodels);
+        return this;
     }
 
-    return this.model;
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Extract SVG element.
-   * @return stringified SVG element.
-   */
-  getSVG() {
-    return this.application.getSVG();
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get demo scenarios, allowing initialization in demo mode from the outside.
-   * @returns {Scenarios}
-   */
-  getDemoScenarios() {
-    return new Scenarios();
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Create new model.
-   * @param metamodelIdOrDefinition
-   * @return newly-created model.
-   */
-  newModel(metamodelIdOrDefinition) {
-    const metamodel = this.getMetamodel(metamodelIdOrDefinition);
-    Common.assertInstanceOf(metamodel, Metamodel);
-    const model = new Model({}, metamodel);
-    if (this.application) {
-      this.application.setModel(model);
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Set current diagram.
+     * @param modelJSON JSON diagram spec.
+     * @param metamodelIdOrDefinition optional metamodel definition or reference. Defaults to
+     * the model's metadata @ref, or the default (permissive) metamodel.
+     * @return this.
+     */
+    setModel(modelJSON, metamodelIdOrDefinition) {
+        Common.assertType(modelJSON, 'Object');
+        const ref = modelJSON.metadata ? modelJSON.metadata.ref : undefined;
+        const metamodel = this.getMetamodel(metamodelIdOrDefinition || ref);
+        Common.assertInstanceOf(metamodel, Metamodel);
+        this.model = new Model(modelJSON, metamodel);
+        if (this.application) {
+            this.application.setModel(this.model);
+        }
+        return this;
     }
-    return model;
-  }
-
-  // //////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get Metamodel instance corresponding to an ID or JSON definition.
-   * @param metamodelIdOrDefinition String ID or JSON definition.
-   * @returns Metamodel instance.
-   * @private
-   */
-  getMetamodel(metamodelIdOrDefinition) {
-    const metamodelType = Common.getType(metamodelIdOrDefinition);
-    if (metamodelType === 'Object') {
-      return new Metamodel(metamodelIdOrDefinition);
+
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get current diagram state. At any given instant the diagram might not make *sense*
+     * but it should always be syntactically valid.
+     * @return current Model.
+     */
+    getModel() {
+        if (this.application) {
+            const model = this.application.getModel();
+            if (model) {
+                return model.unwrap();
+            }
+        }
+
+        return this.model;
     }
-    return this.metamodels.getMetamodelOrDefault(metamodelIdOrDefinition);
-  }
 
-  // //////////////////////////////////////////////////////////////////////////////////////////////
+    // //////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Render current diagram state.
-   */
-  render() {
+    /**
+     * Extract SVG element.
+     * @return stringified SVG element.
+     */
+    getSVG() {
+        return this.application.getSVG();
+    }
 
-    if (this.props.model) {
+    // //////////////////////////////////////////////////////////////////////////////////////////////
 
-      // If a model was specified as a property, apply it. Otherwise
-      // fall back to the demo model.
+    /**
+     * Get demo scenarios, allowing initialization in demo mode from the outside.
+     * @returns {Scenarios}
+     */
+    getDemoScenarios() {
+        return new Scenarios();
+    }
 
-      const scenarios = this.getDemoScenarios();
-      const metamodel = [scenarios.getBlankMetamodel(), scenarios.getECOMPMetamodel()];
-      if (this.props.metamodel) {
-        metamodel.push(this.props.metamodel);
-      }
-      this.setMetamodel(metamodel);
-      this.setModel(this.props.model);
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Create new model.
+     * @param metamodelIdOrDefinition
+     * @return newly-created model.
+     */
+    newModel(metamodelIdOrDefinition) {
+        const metamodel = this.getMetamodel(metamodelIdOrDefinition);
+        Common.assertInstanceOf(metamodel, Metamodel);
+        const model = new Model({}, metamodel);
+        if (this.application) {
+            this.application.setModel(model);
+        }
+        return model;
     }
 
-    return (
-      <Application options={this.options} sequencer={this} ref={(a) => { this.application = a; }} />
-    );
-  }
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get Metamodel instance corresponding to an ID or JSON definition.
+     * @param metamodelIdOrDefinition String ID or JSON definition.
+     * @returns Metamodel instance.
+     * @private
+     */
+    getMetamodel(metamodelIdOrDefinition) {
+        const metamodelType = Common.getType(metamodelIdOrDefinition);
+        if (metamodelType === 'Object') {
+            return new Metamodel(metamodelIdOrDefinition);
+        }
+        return this.metamodels.getMetamodelOrDefault(metamodelIdOrDefinition);
+    }
 
+    // //////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render current diagram state.
+     */
+    render() {
+        if (this.props.model) {
+            // If a model was specified as a property, apply it. Otherwise
+            // fall back to the demo model.
+
+            const scenarios = this.getDemoScenarios();
+            const metamodel = [
+                scenarios.getBlankMetamodel(),
+                scenarios.getECOMPMetamodel()
+            ];
+            if (this.props.metamodel) {
+                metamodel.push(this.props.metamodel);
+            }
+            this.setMetamodel(metamodel);
+            this.setModel(this.props.model);
+        }
+
+        return (
+            <Application
+                options={this.options}
+                sequencer={this}
+                ref={a => {
+                    this.application = a;
+                }}
+            />
+        );
+    }
 }
 
 Sequencer.propTypes = {
-  options: PropTypes.object.isRequired,
-  model: PropTypes.object,
-  metamodel: PropTypes.object,
+    options: PropTypes.object.isRequired,
+    model: PropTypes.object,
+    metamodel: PropTypes.object
 };
 
-
 export default Sequencer;
index 7337367..1c6bd69 100644 (file)
  * Common operations.
  */
 export default class Common {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Retrieve and start a simple timer. Retrieve elapsed time by calling #ms().
+     * @returns {*}
+     */
+    static timer() {
+        const start = new Date().getTime();
+        return {
+            ms() {
+                return new Date().getTime() - start;
+            }
+        };
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Retrieve and start a simple timer. Retrieve elapsed time by calling #ms().
-   * @returns {*}
-   */
-  static timer() {
-    const start = new Date().getTime();
-    return {
-      ms() {
-        return (new Date().getTime() - start);
-      },
-    };
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get datatype, stripping '[object Boolean]' to just 'Boolean'.
-   * @param o JS object.
-   * @return String like String, Number, Date, Null, Undefined, stuff like that.
-   */
-  static getType(o) {
-    const str = Object.prototype.toString.call(o);
-    const prefix = '[object ';
-    if (str.substr(str, prefix.length) === prefix) {
-      return str.substr(prefix.length, str.length - (prefix.length + 1));
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get datatype, stripping '[object Boolean]' to just 'Boolean'.
+     * @param o JS object.
+     * @return String like String, Number, Date, Null, Undefined, stuff like that.
+     */
+    static getType(o) {
+        const str = Object.prototype.toString.call(o);
+        const prefix = '[object ';
+        if (str.substr(str, prefix.length) === prefix) {
+            return str.substr(prefix.length, str.length - (prefix.length + 1));
+        }
+        return str;
     }
-    return str;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert that an argument was provided.
-   * @param value to be checked.
-   * @param message message on assertion failure.
-   * @return value.
-   */
-  static assertNotNull(value, message = 'Unexpected null value') {
-    if (!value) {
-      throw new Error(message);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert that an argument was provided.
+     * @param value to be checked.
+     * @param message message on assertion failure.
+     * @return value.
+     */
+    static assertNotNull(value, message = 'Unexpected null value') {
+        if (!value) {
+            throw new Error(message);
+        }
+        return value;
     }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert argument type.
-   * @param value to be checked.
-   * @param expected expected type string, e,g. Number from [object Number].
-   * @return value.
-   */
-  static assertType(value, expected) {
-    const type = this.getType(value);
-    if (type !== expected) {
-      throw new Error(`Expected type ${expected}, got ${type}`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert argument type.
+     * @param value to be checked.
+     * @param expected expected type string, e,g. Number from [object Number].
+     * @return value.
+     */
+    static assertType(value, expected) {
+        const type = this.getType(value);
+        if (type !== expected) {
+            throw new Error(`Expected type ${expected}, got ${type}`);
+        }
+        return value;
     }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert argument type.
-   * @param value to be checked.
-   * @param unexpected unexpected type string, e,g. Number from [object Number].
-   * @return value.
-   */
-  static assertNotType(value, unexpected) {
-    const type = this.getType(value);
-    if (type === unexpected) {
-      throw new Error(`Forbidden type "${unexpected}"`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert argument type.
+     * @param value to be checked.
+     * @param unexpected unexpected type string, e,g. Number from [object Number].
+     * @return value.
+     */
+    static assertNotType(value, unexpected) {
+        const type = this.getType(value);
+        if (type === unexpected) {
+            throw new Error(`Forbidden type "${unexpected}"`);
+        }
+        return value;
     }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert argument is a simple JSON object, and specifically not (something like an) ES6 class.
-   * @param value to be checked.
-   * @return value.
-   */
-  static assertPlainObject(value) {
-    Common.assertType(value, 'Object');
-    // TODO
-    /*
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert argument is a simple JSON object, and specifically not (something like an) ES6 class.
+     * @param value to be checked.
+     * @return value.
+     */
+    static assertPlainObject(value) {
+        Common.assertType(value, 'Object');
+        // TODO
+        /*
     if (!($.isPlainObject(value))) {
       throw new Error(`Expected plain object: ${value}`);
     }
     */
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert argument type.
-   * @param value to be checked.
-   * @param c expected class.
-   * @return value.
-   */
-  static assertInstanceOf(value, c) {
-    Common.assertNotNull(value);
-    if (!(value instanceof c)) {
-      throw new Error(`Expected instanceof ${c}: ${value}`);
-    }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert that a string matches a regex.
-   * @param value value to be tested.
-   * @param re pattern to be applied.
-   * @return value.
-   */
-  static assertMatches(value, re) {
-    this.assertType(value, 'String');
-    this.assertType(re, 'RegExp');
-    if (!re.test(value)) {
-      throw new Error(`Value ${value} doesn't match pattern ${re}`);
+        return value;
     }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Assert the value of a boolean.
-   *
-   * @param bool to be checked.
-   * @param message optional message on assertion failure.
-   * @return value.
-   */
-  static assertThat(bool, message) {
-    if (!bool) {
-      throw new Error(message || `Unexpected: ${bool}`);
-    }
-    return bool;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Verify that a value, generally a function arg, is a DOM element.
-   * @param value to be checked.
-   * @return value.
-   */
-  static assertHTMLElement(value) {
-    if (!Common.isHTMLElement(value)) {
-      throw new Error(`Expected HTMLElement: ${value}`);
-    }
-    return value;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Check whether a value, generally a function arg, is an HTML DOM element.
-   * @param o to be checked.
-   * @return true if DOM element.
-   */
-  static isHTMLElement(o) {
-    if (typeof HTMLElement === 'object') {
-      return o instanceof HTMLElement;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert argument type.
+     * @param value to be checked.
+     * @param c expected class.
+     * @return value.
+     */
+    static assertInstanceOf(value, c) {
+        Common.assertNotNull(value);
+        if (!(value instanceof c)) {
+            throw new Error(`Expected instanceof ${c}: ${value}`);
+        }
+        return value;
     }
-    return o && typeof o === 'object' && o !== null
-      && o.nodeType === 1 && typeof o.nodeName === 'string';
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Check if a string is non-empty.
-   * @param s string to be checked.
-   * @returns false if non-blank string, true otherwise.
-   */
-  static isBlank(s) {
-    if (Common.getType(s) === 'String') {
-      return (s.trim().length === 0);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert that a string matches a regex.
+     * @param value value to be tested.
+     * @param re pattern to be applied.
+     * @return value.
+     */
+    static assertMatches(value, re) {
+        this.assertType(value, 'String');
+        this.assertType(re, 'RegExp');
+        if (!re.test(value)) {
+            throw new Error(`Value ${value} doesn't match pattern ${re}`);
+        }
+        return value;
     }
-    return true;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Detect dates that are numbers, milli/seconds since epoch..
-   *
-   * @param n candidate number.
-   * @returns {boolean}
-   */
-  static isNumber(n) {
-    return !isNaN(parseFloat(n)) && isFinite(n);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Parse the text output from a template to a DOM element.
-   * @param txt input text.
-   * @returns {Element}
-   */
-  static txt2dom(txt) {
-    return new DOMParser().parseFromString(txt, 'image/svg+xml').documentElement;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Recursively convert a DOM element to an SVG (namespaced) element. Otherwise
-   * you get HTML elements that *happen* to have SVG names, but which aren't actually SVG.
-   *
-   * @param node DOM node to be converted.
-   * @param svg to be updated.
-   * @returns {*} for chaining.
-   */
-  static dom2svg(node, svg) {
-
-    Common.assertNotType(node, 'String');
-
-    if (node.childNodes && node.childNodes.length > 0) {
-
-      for (const c of node.childNodes) {
-        switch (c.nodeType) {
-          case document.TEXT_NODE:
-            svg.text(c.nodeValue);
-            break;
-          default:
-            break;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert the value of a boolean.
+     *
+     * @param bool to be checked.
+     * @param message optional message on assertion failure.
+     * @return value.
+     */
+    static assertThat(bool, message) {
+        if (!bool) {
+            throw new Error(message || `Unexpected: ${bool}`);
         }
-      }
-
-      for (const c of node.childNodes) {
-        switch (c.nodeType) {
-          case document.ELEMENT_NODE:
-            Common.dom2svg(c, svg.append(`svg:${c.nodeName.toLowerCase()}`));
-            break;
-          default:
-            break;
+        return bool;
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Verify that a value, generally a function arg, is a DOM element.
+     * @param value to be checked.
+     * @return value.
+     */
+    static assertHTMLElement(value) {
+        if (!Common.isHTMLElement(value)) {
+            throw new Error(`Expected HTMLElement: ${value}`);
         }
-      }
+        return value;
     }
 
-    if (node.hasAttributes()) {
-      for (let i = 0; i < node.attributes.length; i++) {
-        const a = node.attributes.item(i);
-        svg.attr(a.name, a.value);
-      }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Check whether a value, generally a function arg, is an HTML DOM element.
+     * @param o to be checked.
+     * @return true if DOM element.
+     */
+    static isHTMLElement(o) {
+        /* eslint-disable no-undef */
+        if (typeof HTMLElement === 'object') {
+            return o instanceof HTMLElement;
+        }
+        /* eslint-enable no-undef */
+        return (
+            o &&
+            typeof o === 'object' &&
+            o !== null &&
+            o.nodeType === 1 &&
+            typeof o.nodeName === 'string'
+        );
     }
 
-    return svg;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get the lines to be shown in the label.
-   *
-   * @param labelText original label text.
-   * @param wordWrapAt chars at which to break words.
-   * @param lineWrapAt chars at which to wrap.
-   * @param maximumLines lines at which to truncate.
-   * @returns {Array}
-   */
-  static tokenize(labelText = '', wordWrapAt, lineWrapAt, maximumLines) {
-
-    let l = labelText;
-
-    // Hyphenate and break long words.
-
-    const regex = new RegExp(`(\\w{${wordWrapAt - 1}})(?=\\w)`, 'g');
-    l = l.replace(regex, '$1- ');
-
-    const labelTokens = l.split(/\s+/);
-    const lines = [];
-    let label = '';
-    for (const labelToken of labelTokens) {
-      if (label.length > 0) {
-        const length = label.length + labelToken.length + 1;
-        if (length > lineWrapAt) {
-          lines.push(label.trim());
-          label = labelToken;
-          continue;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Check if a string is non-empty.
+     * @param s string to be checked.
+     * @returns false if non-blank string, true otherwise.
+     */
+    static isBlank(s) {
+        if (Common.getType(s) === 'String') {
+            return s.trim().length === 0;
         }
-      }
-      label = `${label} ${labelToken}`;
+        return true;
     }
 
-    if (label) {
-      lines.push(label.trim());
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Detect dates that are numbers, milli/seconds since epoch..
+     *
+     * @param n candidate number.
+     * @returns {boolean}
+     */
+    static isNumber(n) {
+        return !isNaN(parseFloat(n)) && isFinite(n);
     }
 
-    const truncated = lines.slice(0, maximumLines);
-    if (truncated.length < lines.length) {
-      let finalLine = truncated[maximumLines - 1];
-      if (finalLine.length > (lineWrapAt - 4)) {
-        finalLine = finalLine.substring(0, lineWrapAt - 4);
-      }
-      finalLine = `${finalLine} ...`;
-      truncated[maximumLines - 1] = finalLine;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Parse the text output from a template to a DOM element.
+     * @param txt input text.
+     * @returns {Element}
+     */
+    static txt2dom(txt) {
+        /* eslint-disable no-undef */
+        return new DOMParser().parseFromString(txt, 'image/svg+xml')
+            .documentElement;
+        /* eslint-enable no-undef */
     }
 
-    return truncated;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Brutally sanitize an input string. We have no syntax rules, and hence no specific
-   * rules to apply, but we have very few unconstrained fields, so we can implement a
-   * crude default and devolve the rest to options.
-   * @param value value to be sanitized.
-   * @param options control options including validation rules.
-   * @param type validation type.
-   * @returns {*} sanitized string.
-   * @private
-   */
-  static sanitizeText(value, options, type) {
-    const rules = Common.assertNotNull(options.validation[type]);
-    let v = value || rules.defaultValue || '';
-    if (rules.replace) {
-      v = v.replace(rules.replace, '');
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Recursively convert a DOM element to an SVG (namespaced) element. Otherwise
+     * you get HTML elements that *happen* to have SVG names, but which aren't actually SVG.
+     *
+     * @param node DOM node to be converted.
+     * @param svg to be updated.
+     * @returns {*} for chaining.
+     */
+    static dom2svg(node, svg) {
+        Common.assertNotType(node, 'String');
+
+        if (node.childNodes && node.childNodes.length > 0) {
+            for (const c of node.childNodes) {
+                switch (c.nodeType) {
+                    case document.TEXT_NODE:
+                        svg.text(c.nodeValue);
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            for (const c of node.childNodes) {
+                switch (c.nodeType) {
+                    case document.ELEMENT_NODE:
+                        Common.dom2svg(
+                            c,
+                            svg.append(`svg:${c.nodeName.toLowerCase()}`)
+                        );
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        if (node.hasAttributes()) {
+            for (let i = 0; i < node.attributes.length; i++) {
+                const a = node.attributes.item(i);
+                svg.attr(a.name, a.value);
+            }
+        }
+
+        return svg;
     }
-    if (v.length > rules.maxLength) {
-      v = `${v.substring(0, rules.maxLength)}...`;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get the lines to be shown in the label.
+     *
+     * @param labelText original label text.
+     * @param wordWrapAt chars at which to break words.
+     * @param lineWrapAt chars at which to wrap.
+     * @param maximumLines lines at which to truncate.
+     * @returns {Array}
+     */
+    static tokenize(labelText = '', wordWrapAt, lineWrapAt, maximumLines) {
+        let l = labelText;
+
+        // Hyphenate and break long words.
+
+        const regex = new RegExp(`(\\w{${wordWrapAt - 1}})(?=\\w)`, 'g');
+        l = l.replace(regex, '$1- ');
+
+        const labelTokens = l.split(/\s+/);
+        const lines = [];
+        let label = '';
+        for (const labelToken of labelTokens) {
+            if (label.length > 0) {
+                const length = label.length + labelToken.length + 1;
+                if (length > lineWrapAt) {
+                    lines.push(label.trim());
+                    label = labelToken;
+                    continue;
+                }
+            }
+            label = `${label} ${labelToken}`;
+        }
+
+        if (label) {
+            lines.push(label.trim());
+        }
+
+        const truncated = lines.slice(0, maximumLines);
+        if (truncated.length < lines.length) {
+            let finalLine = truncated[maximumLines - 1];
+            if (finalLine.length > lineWrapAt - 4) {
+                finalLine = finalLine.substring(0, lineWrapAt - 4);
+            }
+            finalLine = `${finalLine} ...`;
+            truncated[maximumLines - 1] = finalLine;
+        }
+
+        return truncated;
     }
-    return v;
-  }
 
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Brutally sanitize an input string. We have no syntax rules, and hence no specific
+     * rules to apply, but we have very few unconstrained fields, so we can implement a
+     * crude default and devolve the rest to options.
+     * @param value value to be sanitized.
+     * @param options control options including validation rules.
+     * @param type validation type.
+     * @returns {*} sanitized string.
+     * @private
+     */
+    static sanitizeText(value, options, type) {
+        const rules = Common.assertNotNull(options.validation[type]);
+        let v = value || rules.defaultValue || '';
+        if (rules.replace) {
+            v = v.replace(rules.replace, '');
+        }
+        if (v.length > rules.maxLength) {
+            v = `${v.substring(0, rules.maxLength)}...`;
+        }
+        return v;
+    }
 }
index 187f49b..8b6ae67 100644 (file)
@@ -23,108 +23,107 @@ import Common from './Common';
  * disable them for production.
  */
 export default class Logger {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * No-op call so that we can leave imports in place,
+     * even when there's no debugging.
+     */
+    static noop() {
+        // Nothing.
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Set debug level.
+     * @param level threshold.
+     */
+    static setLevel(level) {
+        this.level = Logger.OFF;
+        if (Common.getType(level) === 'Number') {
+            this.level = level;
+        } else {
+            this.level = Logger[level];
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get debug level.
+     * @returns {number|*}
+     */
+    static getLevel() {
+        return this.level;
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * No-op call so that we can leave imports in place,
-   * even when there's no debugging.
-   */
-  static noop() {
-    // Nothing.
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Set debug level.
-   * @param level threshold.
-   */
-  static setLevel(level) {
-    this.level = Logger.OFF;
-    if (Common.getType(level) === 'Number') {
-      this.level = level;
-    } else {
-      this.level = Logger[level];
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Write DEBUG-level log.
+     * @param msg message or tokens.
+     */
+    static debug(...msg) {
+        if (this.level >= Logger.DEBUG) {
+            const out = this.serialize(msg);
+            console.info(`ASDCS [DEBUG] ${out}`);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get debug level.
-   * @returns {number|*}
-   */
-  static getLevel() {
-    return this.level;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Write DEBUG-level log.
-   * @param msg message or tokens.
-   */
-  static debug(...msg) {
-    if (this.level >= Logger.DEBUG) {
-      const out = this.serialize(msg);
-      console.info(`ASDCS [DEBUG] ${out}`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Write INFO-level log.
+     * @param msg message or tokens.
+     */
+    static info(...msg) {
+        if (this.level >= Logger.INFO) {
+            const out = this.serialize(msg);
+            console.info(`ASDCS [INFO] ${out}`);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Write INFO-level log.
-   * @param msg message or tokens.
-   */
-  static info(...msg) {
-    if (this.level >= Logger.INFO) {
-      const out = this.serialize(msg);
-      console.info(`ASDCS [INFO] ${out}`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Write debug.
+     * @param msg message or tokens.
+     */
+    static warn(msg) {
+        if (this.level >= Logger.WARN) {
+            const out = this.serialize(msg);
+            console.warn(`ASDCS [WARN] ${out}`);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Write debug.
-   * @param msg message or tokens.
-   */
-  static warn(msg) {
-    if (this.level >= Logger.WARN) {
-      const out = this.serialize(msg);
-      console.warn(`ASDCS [WARN] ${out}`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Write error.
+     * @param msg message or tokens.
+     */
+    static error(...msg) {
+        if (this.level >= Logger.ERROR) {
+            const out = this.serialize(msg);
+            console.error(`ASDCS [ERROR] ${out}`);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Write error.
-   * @param msg message or tokens.
-   */
-  static error(...msg) {
-    if (this.level >= Logger.ERROR) {
-      const out = this.serialize(msg);
-      console.error(`ASDCS [ERROR] ${out}`);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Serialize msg.
+     * @param msg message or tokens.
+     * @returns {string}
+     */
+    static serialize(...msg) {
+        let out = '';
+        msg.forEach(token => {
+            out = `${out}${token}`;
+        });
+        return out;
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Serialize msg.
-   * @param msg message or tokens.
-   * @returns {string}
-   */
-  static serialize(...msg) {
-    let out = '';
-    msg.forEach((token) => {
-      out = `${out}${token}`;
-    });
-    return out;
-  }
 }
 
 // /////////////////////////////////////////////////////////////////////////////////////////////////
index 15897d7..b054cb2 100644 (file)
@@ -23,26 +23,25 @@ import Logger from './Logger';
  * and the result -- runtime options -- are available by calling #getOptions().
  */
 export default class Options {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Construct options, applying defaults.
+     * @param options optional override options.
+     */
+    constructor(options = {}) {
+        this.options = _merge({}, Options.DEFAULTS, options);
+    }
 
-  /**
-   * Construct options, applying defaults.
-   * @param options optional override options.
-   */
-  constructor(options = {}) {
-    this.options = _merge({}, Options.DEFAULTS, options);
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Unwrap options.
-   * @returns {*}
-   */
-  unwrap() {
-    return this.options;
-  }
+    /**
+     * Unwrap options.
+     * @returns {*}
+     */
+    unwrap() {
+        return this.options;
+    }
 }
 
 // /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -51,86 +50,86 @@ export default class Options {
  * Default options, overridden by anything of the same name.
  */
 Options.DEFAULTS = {
-  log: {
-    level: Logger.WARN,
-  },
-  demo: false,
-  useHtmlSelect: true,
-  diagram: {
-    svg: {
-      x: 0,
-      y: 0,
-      width: 1600,
-      height: 1200,
-      margin: 50,
-      floodColor: '#009fdb',
-      scale: {
-        height: true,
-        width: true,
-        minimum: 0.25,
-      },
-    },
-    title: {
-      height: 0,
-    },
-    metadata: false,
-    lifelines: {
-      header: {
-        height: 225,
-        width: 350,
-        wrapWords: 14,
-        wrapLines: 18,
-        maxLines: 5,
-      },
-      occurrences: {
-        marginTop: 50,
-        marginBottom: 75,
-        foreshortening: 5,
-        width: 50,
-      },
-      spacing: {
-        horizontal: 400,
-        vertical: 400,
-      },
-    },
-    messages: {
-      label: {
-        wrapWords: 14,
-        wrapLines: 18,
-        maxLines: 4,
-      },
-    },
-    fragments: {
-      leftMargin: 150,
-      topMargin: 200,
-      widthMargin: 300,
-      heightMargin: 350,
-      label: {
-        wrapWords: 50,
-        wrapLines: 50,
-        maxLines: 2,
-      },
-    },
-  },
-  validation: {
-    lifeline: {
-      maxLength: 100,
-      defaultValue: '',
-      replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g,
-    },
-    message: {
-      maxLength: 100,
-      defaultValue: '',
-      replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g,
-    },
-    notes: {
-      maxLength: 255,
-      defaultValue: '',
+    log: {
+        level: Logger.WARN
     },
-    guard: {
-      maxLength: 80,
-      defaultValue: '',
-      replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g,
+    demo: false,
+    useHtmlSelect: true,
+    diagram: {
+        svg: {
+            x: 0,
+            y: 0,
+            width: 1600,
+            height: 1200,
+            margin: 50,
+            floodColor: '#009fdb',
+            scale: {
+                height: true,
+                width: true,
+                minimum: 0.25
+            }
+        },
+        title: {
+            height: 0
+        },
+        metadata: false,
+        lifelines: {
+            header: {
+                height: 225,
+                width: 350,
+                wrapWords: 14,
+                wrapLines: 18,
+                maxLines: 5
+            },
+            occurrences: {
+                marginTop: 50,
+                marginBottom: 75,
+                foreshortening: 5,
+                width: 50
+            },
+            spacing: {
+                horizontal: 400,
+                vertical: 400
+            }
+        },
+        messages: {
+            label: {
+                wrapWords: 14,
+                wrapLines: 18,
+                maxLines: 4
+            }
+        },
+        fragments: {
+            leftMargin: 150,
+            topMargin: 200,
+            widthMargin: 300,
+            heightMargin: 350,
+            label: {
+                wrapWords: 50,
+                wrapLines: 50,
+                maxLines: 2
+            }
+        }
     },
-  },
+    validation: {
+        lifeline: {
+            maxLength: 100,
+            defaultValue: '',
+            replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g
+        },
+        message: {
+            maxLength: 100,
+            defaultValue: '',
+            replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g
+        },
+        notes: {
+            maxLength: 255,
+            defaultValue: ''
+        },
+        guard: {
+            maxLength: 80,
+            defaultValue: '',
+            replace: /[^\-\.\+ &%#@\?\(\)\[\]<>\w\d]/g
+        }
+    }
 };
index 6889e0a..b63e69a 100644 (file)
@@ -28,258 +28,274 @@ import Overlay from '../overlay/Overlay';
  * Application controller, also a view.
  */
 class Application extends React.Component {
+    /**
+     * Construct application view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        this.sequencer = Common.assertNotNull(props.sequencer);
+        this.model = this.sequencer.getModel();
+        this.metamodel = this.sequencer.getMetamodel();
+        this.options = props.options;
+        Logger.setLevel(this.options.unwrap().log.level);
+
+        // Bindings.
+
+        this.showInfoDialog = this.showInfoDialog.bind(this);
+        this.showEditDialog = this.showEditDialog.bind(this);
+        this.showConfirmDialog = this.showConfirmDialog.bind(this);
+        this.hideOverlay = this.hideOverlay.bind(this);
+        this.onMouseMove = this.onMouseMove.bind(this);
+        this.onMouseUp = this.onMouseUp.bind(this);
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Construct application view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-
-    this.sequencer = Common.assertNotNull(props.sequencer);
-    this.model = this.sequencer.getModel();
-    this.metamodel = this.sequencer.getMetamodel();
-    this.options = props.options;
-    Logger.setLevel(this.options.unwrap().log.level);
-
-    // Bindings.
-
-    this.showInfoDialog = this.showInfoDialog.bind(this);
-    this.showEditDialog = this.showEditDialog.bind(this);
-    this.showConfirmDialog = this.showConfirmDialog.bind(this);
-    this.hideOverlay = this.hideOverlay.bind(this);
-    this.onMouseMove = this.onMouseMove.bind(this);
-    this.onMouseUp = this.onMouseUp.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get application options.
-   * @returns JSON options, see Options.js.
-   */
-  getOptions() {
-    return this.options.unwrap();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Set diagram name.
-   * @param n diagram (human-readable) name.
-   */
-  setName(n) {
-    this.diagram.setName(n);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Set diagram model.
-   * @param model diagram instance.
-   */
-  setModel(model) {
-
-    Common.assertNotNull(model);
-
-    this.model = model;
-
-    if (this.editor) {
-      this.editor.render();
+    /**
+     * Get application options.
+     * @returns JSON options, see Options.js.
+     */
+    getOptions() {
+        return this.options.unwrap();
     }
 
-    if (this.diagram) {
-      this.diagram.render();
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Set diagram name.
+     * @param n diagram (human-readable) name.
+     */
+    setName(n) {
+        this.diagram.setName(n);
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get Model wrapper.
-   * @returns Model.
-   */
-  getModel() {
-    return this.model;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get SVG element.
-   * @returns {*}
-   */
-  getSVG() {
-    return this.diagram.getSVG();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get top-level widget. Provides the demo toolbar with access to the public API.
-   * @returns {*}
-   */
-  getSequencer() {
-    return this.sequencer;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Present info dialog.
-   * @param msg info message.
-   */
-  showInfoDialog(msg) {
-    this.dialog.showInfoDialog(msg);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Present error dialog.
-   * @param msg error message.
-   */
-  showErrorDialog(msg) {
-    this.dialog.showErrorDialog(msg);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Present confirmation dialog.
-   * @param msg info message.
-   * @param cb callback function to be invoked on OK.
-   */
-  showConfirmDialog(msg, cb) {
-    Common.assertType(cb, 'Function');
-    this.dialog.showConfirmDialog(msg, cb);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Present edit (textarea) dialog.
-   * @param msg prompt.
-   * @param text current edit text.
-   * @param cb callback function to be invoked on OK, taking the updated text
-   * as an argument.
-   */
-  showEditDialog(msg, text, cb) {
-    this.dialog.showEditDialog(msg, text, cb);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Select lifeline by ID.
-   * @param id lifeline ID.
-   */
-  selectLifeline(id) {
-    if (this.editor) {
-      this.editor.selectLifeline(id);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Set diagram model.
+     * @param model diagram instance.
+     */
+    setModel(model) {
+        Common.assertNotNull(model);
+
+        this.model = model;
+
+        if (this.editor) {
+            this.editor.render();
+        }
+
+        if (this.diagram) {
+            this.diagram.render();
+        }
     }
-    if (this.diagram) {
-      this.diagram.selectLifeline(id);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get Model wrapper.
+     * @returns Model.
+     */
+    getModel() {
+        return this.model;
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Select message by ID.
-   * @param id message ID.
-   */
-  selectMessage(id) {
-    if (this.editor) {
-      this.editor.selectMessage(id);
+    /**
+     * Get SVG element.
+     * @returns {*}
+     */
+    getSVG() {
+        return this.diagram.getSVG();
     }
-    if (this.diagram) {
-      this.diagram.selectMessage(id);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get top-level widget. Provides the demo toolbar with access to the public API.
+     * @returns {*}
+     */
+    getSequencer() {
+        return this.sequencer;
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * (Re)render just the diagram.
-   */
-  renderDiagram() {
-    this.diagram.redraw();
-  }
+    /**
+     * Present info dialog.
+     * @param msg info message.
+     */
+    showInfoDialog(msg) {
+        this.dialog.showInfoDialog(msg);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Show overlay between application and modal dialog.
-   */
-  showOverlay() {
-    if (this.overlay) {
-      this.overlay.setVisible(true);
+    /**
+     * Present error dialog.
+     * @param msg error message.
+     */
+    showErrorDialog(msg) {
+        this.dialog.showErrorDialog(msg);
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Present confirmation dialog.
+     * @param msg info message.
+     * @param cb callback function to be invoked on OK.
+     */
+    showConfirmDialog(msg, cb) {
+        Common.assertType(cb, 'Function');
+        this.dialog.showConfirmDialog(msg, cb);
+    }
 
-  /**
-   * Hide overlay between application and modal dialog.
-   */
-  hideOverlay() {
-    if (this.overlay) {
-      this.overlay.setVisible(false);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Present edit (textarea) dialog.
+     * @param msg prompt.
+     * @param text current edit text.
+     * @param cb callback function to be invoked on OK, taking the updated text
+     * as an argument.
+     */
+    showEditDialog(msg, text, cb) {
+        this.dialog.showEditDialog(msg, text, cb);
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select lifeline by ID.
+     * @param id lifeline ID.
+     */
+    selectLifeline(id) {
+        if (this.editor) {
+            this.editor.selectLifeline(id);
+        }
+        if (this.diagram) {
+            this.diagram.selectLifeline(id);
+        }
+    }
 
-  /**
-   * Capture mouse move events, for resize.
-   * @param event move event.
-   */
-  onMouseMove(event) {
-    if (this.editor) {
-      this.editor.onMouseMove(event);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select message by ID.
+     * @param id message ID.
+     */
+    selectMessage(id) {
+        if (this.editor) {
+            this.editor.selectMessage(id);
+        }
+        if (this.diagram) {
+            this.diagram.selectMessage(id);
+        }
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Propagate mouse event to the editor that manages the resize.
-   */
-  onMouseUp() {
-    if (this.editor) {
-      this.editor.onMouseUp();
+    /**
+     * (Re)render just the diagram.
+     */
+    renderDiagram() {
+        this.diagram.redraw();
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Render current model state.
-   */
-  render() {
+    /**
+     * Show overlay between application and modal dialog.
+     */
+    showOverlay() {
+        if (this.overlay) {
+            this.overlay.setVisible(true);
+        }
+    }
 
-    return (
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-      <div className="asdcs-control" onMouseMove={this.onMouseMove} onMouseUp={this.onMouseUp}>
+    /**
+     * Hide overlay between application and modal dialog.
+     */
+    hideOverlay() {
+        if (this.overlay) {
+            this.overlay.setVisible(false);
+        }
+    }
 
-        <Editor application={this} ref={(r) => { this.editor = r; }} />
-        <Diagram application={this} ref={(r) => { this.diagram = r; }} />
-        <Dialog application={this} ref={(r) => { this.dialog = r; }} />
-        <Export />
-        <Overlay application={this} ref={(r) => { this.overlay = r; }} />
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-      </div>
-    );
-  }
+    /**
+     * Capture mouse move events, for resize.
+     * @param event move event.
+     */
+    onMouseMove(event) {
+        if (this.editor) {
+            this.editor.onMouseMove(event);
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
+    /**
+     * Propagate mouse event to the editor that manages the resize.
+     */
+    onMouseUp() {
+        if (this.editor) {
+            this.editor.onMouseUp();
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render current model state.
+     */
+    render() {
+        return (
+            <div
+                className="asdcs-control"
+                onMouseMove={this.onMouseMove}
+                onMouseUp={this.onMouseUp}>
+                <Editor
+                    application={this}
+                    ref={r => {
+                        this.editor = r;
+                    }}
+                />
+                <Diagram
+                    application={this}
+                    ref={r => {
+                        this.diagram = r;
+                    }}
+                />
+                <Dialog
+                    application={this}
+                    ref={r => {
+                        this.dialog = r;
+                    }}
+                />
+                <Export />
+                <Overlay
+                    application={this}
+                    ref={r => {
+                        this.overlay = r;
+                    }}
+                />
+            </div>
+        );
+    }
 }
 
 /** React properties. */
 Application.propTypes = {
-  options: PropTypes.object.isRequired,
-  sequencer: PropTypes.object.isRequired,
+    options: PropTypes.object.isRequired,
+    sequencer: PropTypes.object.isRequired
 };
 
 export default Application;
index b3544d7..129a1af 100644 (file)
@@ -28,898 +28,1013 @@ import Popup from './components/popup/Popup';
  * SVG diagram view.
  */
 class Diagram extends React.Component {
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct React view.
-   * @param props properties.
-   * @param context context.
-   */
-  constructor(props, context) {
-    super(props, context);
-
-    this.application = Common.assertNotNull(props.application);
-    this.options = this.application.getOptions().diagram;
-
-    this.events = {};
-    this.state = {
-      height: 0,
-      width: 0,
-    };
-
-    this.templates = {
-      diagram: _template(require('./templates/diagram.html')),
-      lifeline: _template(require('./templates/lifeline.html')),
-      message: _template(require('./templates/message.html')),
-      occurrence: _template(require('./templates/occurrence.html')),
-      fragment: _template(require('./templates/fragment.html')),
-      title: _template(require('./templates/title.html')),
-    };
-
-    this.handleResize = this.handleResize.bind(this);
-    this.initialTransformX = 0;
-    this.initialTransformY = 0;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Set diagram name.
-   * @param n name.
-   */
-  setName(n) {
-    this.svg.select('').text(n);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get SVG from diagram.
-   * @returns {*|string}
-   */
-  getSVG() {
-    const svg = this.svg.node().outerHTML;
-    return svg.replace('<svg ', '<svg xmlns="http://www.w3.org/2000/svg" ');
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Select message by ID.
-   * @param id message ID.
-   */
-  selectMessage(id) {
-    const sel = this.svg.selectAll('g.asdcs-diagram-message-container');
-    sel.classed('asdcs-active', false);
-    sel.selectAll('rect.asdcs-diagram-message-bg').attr('filter', null);
-    if (id) {
-      const parent = this.svg.select(`g.asdcs-diagram-message-container[data-id="${id}"]`);
-      parent.classed('asdcs-active', true);
-      parent.selectAll('rect.asdcs-diagram-message-bg').attr('filter', 'url(#asdcsSvgHighlight)');
-    }
-    this._showNotesPopup(id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Select lifeline by ID.
-   * @param id lifeline ID.
-   */
-  selectLifeline(id) {
-    const sel = this.svg.selectAll('g.asdcs-diagram-lifeline-container');
-    sel.classed('asdcs-active', false);
-    sel.selectAll('rect').attr('filter', null);
-    if (id) {
-      const parent = this.svg.select(`g.asdcs-diagram-lifeline-container[data-id="${id}"]`);
-      parent.selectAll('rect').attr('filter', 'url(#asdcsSvgHighlight)');
-      parent.classed('asdcs-active', true);
-    }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle resize, including initial sizing.
-   */
-  handleResize() {
-    if (this.wrapper) {
-      const height = this.wrapper.offsetHeight;
-      const width = this.wrapper.offsetWidth;
-      if (this.state.height !== height || this.state.width !== width) {
-        this.setState({ height, width });
-      }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct React view.
+     * @param props properties.
+     * @param context context.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        this.application = Common.assertNotNull(props.application);
+        this.options = this.application.getOptions().diagram;
+
+        this.events = {};
+        this.state = {
+            height: 0,
+            width: 0
+        };
+
+        this.templates = {
+            diagram: _template(require('./templates/diagram.html')),
+            lifeline: _template(require('./templates/lifeline.html')),
+            message: _template(require('./templates/message.html')),
+            occurrence: _template(require('./templates/occurrence.html')),
+            fragment: _template(require('./templates/fragment.html')),
+            title: _template(require('./templates/title.html'))
+        };
+
+        this.handleResize = this.handleResize.bind(this);
+        this.initialTransformX = 0;
+        this.initialTransformY = 0;
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * (Re)render diagram.
-   */
-  render() {
-
-    const model = this.application.getModel();
-    const modelJSON = model.unwrap();
-    const name = modelJSON.diagram.metadata.name;
-    const options = this.application.getOptions();
-    const titleHeight = options.diagram.title.height;
-    const titleClass = (titleHeight && titleHeight > 0) ? `height:${titleHeight}` : 'asdcs-hidden';
-
-    return (
-      <div className="asdcs-diagram">
-        <div className={`asdcs-diagram-name ${titleClass}`}>{name}</div>
-        <div className="asdcs-diagram-svg" ref={(r) => { this.wrapper = r; }}></div>
-        <Popup visible={false} ref={(r) => { this.popup = r; }} />
-      </div>
-    );
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  redraw() {
-    this.updateSVG();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Initial render.
-   */
-  componentDidMount() {
-    window.addEventListener('resize', this.handleResize);
-    this.updateSVG();
-
-    // Insurance:
-
-    setTimeout(() => {
-      this.handleResize();
-    }, 500);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  componentWillUnmount() {
-    window.removeEventListener('resize', this.handleResize);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render on update.
-   */
-  componentDidUpdate() {
-    this.updateSVG();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Redraw SVG diagram. So far it's fast enough that it doesn't seem to matter whether
-   * it's completely redrawn.
-   */
-  updateSVG() {
-
-    if (!this.svg) {
-      const svgparams = _merge({}, this.options.svg);
-      this.wrapper.innerHTML = this.templates.diagram(svgparams);
-      this.svg = d3.select(this.wrapper).select('svg');
-    }
-
-    if (this.state.height === 0) {
-
-      // We'll get a resize event, and the height will be non-zero when it's actually time.
 
-      return;
-    }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    if (this.state.height && this.state.width) {
-      const margin = this.options.svg.margin;
-      const x = -margin;
-      const y = -margin;
-      const height = this.state.height + (margin * 2);
-      const width = this.state.width + (margin * 2);
-      const viewBox = `${x} ${y} ${width} ${height}`;
-      this.svg.attr('viewBox', viewBox);
+    /**
+     * Set diagram name.
+     * @param n name.
+     */
+    setName(n) {
+        this.svg.select('').text(n);
     }
 
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    // If we've already rendered, then save the current scale/translate so that we
-    // can reapply it after rendering.
-
-    const gContentSelection = this.svg.selectAll('g.asdcs-diagram-content');
-    if (gContentSelection.size() === 1) {
-      const transform = gContentSelection.attr('transform');
-      if (transform) {
-        this.savedTransform = transform;
-      }
+    /**
+     * Get SVG from diagram.
+     * @returns {*|string}
+     */
+    getSVG() {
+        const svg = this.svg.node().outerHTML;
+        return svg.replace('<svg ', '<svg xmlns="http://www.w3.org/2000/svg" ');
     }
 
-    // Empty the document. We're starting again.
-
-    this.svg.selectAll('.asdcs-diagram-content').remove();
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select message by ID.
+     * @param id message ID.
+     */
+    selectMessage(id) {
+        const sel = this.svg.selectAll('g.asdcs-diagram-message-container');
+        sel.classed('asdcs-active', false);
+        sel.selectAll('rect.asdcs-diagram-message-bg').attr('filter', null);
+        if (id) {
+            const parent = this.svg.select(
+                `g.asdcs-diagram-message-container[data-id="${id}"]`
+            );
+            parent.classed('asdcs-active', true);
+            parent
+                .selectAll('rect.asdcs-diagram-message-bg')
+                .attr('filter', 'url(#asdcsSvgHighlight)');
+        }
+        this._showNotesPopup(id);
+    }
 
-    // Extract the model.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select lifeline by ID.
+     * @param id lifeline ID.
+     */
+    selectLifeline(id) {
+        const sel = this.svg.selectAll('g.asdcs-diagram-lifeline-container');
+        sel.classed('asdcs-active', false);
+        sel.selectAll('rect').attr('filter', null);
+        if (id) {
+            const parent = this.svg.select(
+                `g.asdcs-diagram-lifeline-container[data-id="${id}"]`
+            );
+            parent.selectAll('rect').attr('filter', 'url(#asdcsSvgHighlight)');
+            parent.classed('asdcs-active', true);
+        }
+    }
 
-    const model = this.application.getModel();
-    if (!model) {
-      return;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle resize, including initial sizing.
+     */
+    handleResize() {
+        if (this.wrapper) {
+            const height = this.wrapper.offsetHeight;
+            const width = this.wrapper.offsetWidth;
+            if (this.state.height !== height || this.state.width !== width) {
+                this.setState({ height, width });
+            }
+        }
     }
-    const modelJSON = model.unwrap();
 
-    // Extract dimension options.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * (Re)render diagram.
+     */
+    render() {
+        const model = this.application.getModel();
+        const modelJSON = model.unwrap();
+        const name = modelJSON.diagram.metadata.name;
+        const options = this.application.getOptions();
+        const titleHeight = options.diagram.title.height;
+        const titleClass =
+            titleHeight && titleHeight > 0
+                ? `height:${titleHeight}`
+                : 'asdcs-hidden';
+
+        return (
+            <div className="asdcs-diagram">
+                <div className={`asdcs-diagram-name ${titleClass}`}>{name}</div>
+                <div
+                    className="asdcs-diagram-svg"
+                    ref={r => {
+                        this.wrapper = r;
+                    }}
+                />
+                <Popup
+                    visible={false}
+                    ref={r => {
+                        this.popup = r;
+                    }}
+                />
+            </div>
+        );
+    }
 
-    const header = this.options.lifelines.header;
-    const spacing = this.options.lifelines.spacing;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    // Make separate container elements so that we can control Z order.
+    redraw() {
+        this.updateSVG();
+    }
 
-    const gContent = this.svg.append('g').attr('class', 'asdcs-diagram-content');
-    const gLifelines = gContent.append('g').attr('class', 'asdcs-diagram-lifelines');
-    const gCanvas = gContent.append('g').attr('class', 'asdcs-diagram-canvas');
-    gCanvas.append('g').attr('class', 'asdcs-diagram-occurrences');
-    gCanvas.append('g').attr('class', 'asdcs-diagram-fragments');
-    gCanvas.append('g').attr('class', 'asdcs-diagram-messages');
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    // Lifelines -----------------------------------------------------------------------------------
+    /**
+     * Initial render.
+     */
+    componentDidMount() {
+        window.addEventListener('resize', this.handleResize);
+        this.updateSVG();
 
-    const actorsById = {};
-    const positionsByMessageId = {};
-    const lifelines = [];
-    for (const actor of modelJSON.diagram.lifelines) {
-      const x = (header.width / 2) + (lifelines.length * spacing.horizontal);
-      Diagram._processLifeline(actor, x);
-      lifelines.push({ x, actor });
-      actorsById[actor.id] = actor;
-    }
+        // Insurance:
 
-    // Messages ------------------------------------------------------------------------------------
-
-    // Analyze occurrence information.
-
-    const occurrences = model.analyzeOccurrences();
-    const fragments = model.analyzeFragments();
-    let y = this.options.lifelines.header.height + spacing.vertical;
-    let messageIndex = 0;
-    for (const step of modelJSON.diagram.steps) {
-      if (step.message) {
-        positionsByMessageId[step.message.id] = positionsByMessageId[step.message.id] || {};
-        positionsByMessageId[step.message.id].y = y;
-        this._drawMessage(gCanvas, step.message, y, actorsById,
-          positionsByMessageId, ++messageIndex, occurrences, fragments);
-      }
-      y += spacing.vertical;
+        setTimeout(() => {
+            this.handleResize();
+        }, 500);
     }
 
-    // ---------------------------------------------------------------------------------------------
-
-    // Draw the actual (dashed) lifelines in a background <g>.
-
-    this._drawLifelines(gLifelines, lifelines, y);
-
-    // Initialize mouse event handlers.
-
-    this._initMouseEvents(gLifelines, gCanvas);
-
-    // Scale to fit.
-
-    const bb = gContent.node().getBBox();
-    this._initZoom(gContent, bb.width, bb.height);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Draw message into SVG canvas.
-   * @param gCanvas container.
-   * @param message message to be rendered.
-   * @param y current y position.
-   * @param actorsById actor lookup.
-   * @param positionsByMessageId x- and y-position of each message.
-   * @param messageIndex where we are in the set of messages to be rendered.
-   * @param oData occurrences info.
-   * @param fData fragments info.
-   * @private
-   */
-  _drawMessage(gCanvas, message, y, actorsById, positionsByMessageId,
-               messageIndex, oData, fData) {
-
-    Common.assertNotNull(oData);
-
-    const request = message.type === 'request';
-    const fromActor = request ? actorsById[message.from] : actorsById[message.to];
-    const toActor = request ? actorsById[message.to] : actorsById[message.from];
-
-    if (!fromActor) {
-      Logger.warn(`Cannot draw message ${JSON.stringify(message)}: 'from' not found.`);
-      return;
-    }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    if (!toActor) {
-      Logger.warn(`Cannot draw message ${JSON.stringify(message)}: 'to' not found.`);
-      return;
+    componentWillUnmount() {
+        window.removeEventListener('resize', this.handleResize);
     }
 
-    // Occurrences. --------------------------------------------------------------------------------
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    if (message.occurrence) {
-      Logger.debug(`Found occurrence for ${message.name}: ${JSON.stringify(message.occurrence)}`);
+    /**
+     * Render on update.
+     */
+    componentDidUpdate() {
+        this.updateSVG();
     }
-    const activeTo = Diagram._calcActive(oData, toActor.id);
-    this._drawOccurrence(gCanvas, oData, positionsByMessageId, fromActor, message.id);
-    this._drawOccurrence(gCanvas, oData, positionsByMessageId, toActor, message.id);
-    const activeFrom = Diagram._calcActive(oData, fromActor.id);
-
-    // Messages. -----------------------------------------------------------------------------------
-
-    const gMessages = gCanvas.select('g.asdcs-diagram-messages');
-
-    // Save positions for later.
-
-    const positions = positionsByMessageId[message.id];
-    positions.x0 = fromActor.x;
-    positions.x1 = toActor.x;
-
-    // Calculate.
 
-    const leftToRight = fromActor.x < toActor.x;
-    const loopback = (message.to === message.from);
-    const x1 = this._calcMessageX(activeTo, toActor.x, true, leftToRight);
-    const x0 = loopback ? x1 : this._calcMessageX(activeFrom, fromActor.x, false, leftToRight);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Redraw SVG diagram. So far it's fast enough that it doesn't seem to matter whether
+     * it's completely redrawn.
+     */
+    updateSVG() {
+        if (!this.svg) {
+            const svgparams = _merge({}, this.options.svg);
+            this.wrapper.innerHTML = this.templates.diagram(svgparams);
+            this.svg = d3.select(this.wrapper).select('svg');
+        }
 
-    let messagePath;
-    if (loopback) {
+        if (this.state.height === 0) {
+            // We'll get a resize event, and the height will be non-zero when it's actually time.
 
-      // To self.
+            return;
+        }
 
-      messagePath = `M${x1},${y}`;
-      messagePath = `${messagePath} L${x1 + 200},${y}`;
-      messagePath = `${messagePath} L${x1 + 200},${y + 50}`;
-      messagePath = `${messagePath} L${x1},${y + 50}`;
-    } else {
+        if (this.state.height && this.state.width) {
+            const margin = this.options.svg.margin;
+            const x = -margin;
+            const y = -margin;
+            const height = this.state.height + margin * 2;
+            const width = this.state.width + margin * 2;
+            const viewBox = `${x} ${y} ${width} ${height}`;
+            this.svg.attr('viewBox', viewBox);
+        }
 
-      // Between lifelines.
+        // If we've already rendered, then save the current scale/translate so that we
+        // can reapply it after rendering.
 
-      messagePath = `M${x0},${y}`;
-      messagePath = `${messagePath} L${x1},${y}`;
-    }
+        const gContentSelection = this.svg.selectAll('g.asdcs-diagram-content');
+        if (gContentSelection.size() === 1) {
+            const transform = gContentSelection.attr('transform');
+            if (transform) {
+                this.savedTransform = transform;
+            }
+        }
 
-    const styles = Diagram._getMessageStyles(message);
+        // Empty the document. We're starting again.
 
-    // Split message over lines.
+        this.svg.selectAll('.asdcs-diagram-content').remove();
 
-    const messageWithPrefix = `${messageIndex}. ${message.name}`;
-    const maxLines = this.options.messages.label.maxLines;
-    const wrapWords = this.options.messages.label.wrapWords;
-    const wrapLines = this.options.messages.label.wrapLines;
-    const messageLines = Common.tokenize(messageWithPrefix, wrapWords, wrapLines, maxLines);
+        // Extract the model.
 
-    const messageTxt = this.templates.message({
-      id: message.id,
-      classes: styles.css,
-      marker: styles.marker,
-      dasharray: styles.dasharray,
-      labels: messageLines,
-      lines: maxLines,
-      path: messagePath,
-      index: messageIndex,
-      x0, x1, y,
-    });
+        const model = this.application.getModel();
+        if (!model) {
+            return;
+        }
+        const modelJSON = model.unwrap();
+
+        // Extract dimension options.
+
+        const header = this.options.lifelines.header;
+        const spacing = this.options.lifelines.spacing;
+
+        // Make separate container elements so that we can control Z order.
+
+        const gContent = this.svg
+            .append('g')
+            .attr('class', 'asdcs-diagram-content');
+        const gLifelines = gContent
+            .append('g')
+            .attr('class', 'asdcs-diagram-lifelines');
+        const gCanvas = gContent
+            .append('g')
+            .attr('class', 'asdcs-diagram-canvas');
+        gCanvas.append('g').attr('class', 'asdcs-diagram-occurrences');
+        gCanvas.append('g').attr('class', 'asdcs-diagram-fragments');
+        gCanvas.append('g').attr('class', 'asdcs-diagram-messages');
+
+        // Lifelines -----------------------------------------------------------------------------------
+
+        const actorsById = {};
+        const positionsByMessageId = {};
+        const lifelines = [];
+        for (const actor of modelJSON.diagram.lifelines) {
+            const x = header.width / 2 + lifelines.length * spacing.horizontal;
+            Diagram._processLifeline(actor, x);
+            lifelines.push({ x, actor });
+            actorsById[actor.id] = actor;
+        }
 
-    const messageEl = Common.txt2dom(messageTxt);
-    const gMessage = gMessages.append('g');
-    Common.dom2svg(messageEl, gMessage);
+        // Messages ------------------------------------------------------------------------------------
+
+        // Analyze occurrence information.
+
+        const occurrences = model.analyzeOccurrences();
+        const fragments = model.analyzeFragments();
+        let y = this.options.lifelines.header.height + spacing.vertical;
+        let messageIndex = 0;
+        for (const step of modelJSON.diagram.steps) {
+            if (step.message) {
+                positionsByMessageId[step.message.id] =
+                    positionsByMessageId[step.message.id] || {};
+                positionsByMessageId[step.message.id].y = y;
+                this._drawMessage(
+                    gCanvas,
+                    step.message,
+                    y,
+                    actorsById,
+                    positionsByMessageId,
+                    ++messageIndex,
+                    occurrences,
+                    fragments
+                );
+            }
+            y += spacing.vertical;
+        }
 
-    // Set the background's bounding box to that of the text,
-    // so that they fit snugly.
+        // ---------------------------------------------------------------------------------------------
 
-    const labelBB = gMessage.select('.asdcs-diagram-message-label').node().getBBox();
-    gMessage.select('.asdcs-diagram-message-label-bg')
-      .attr('x', labelBB.x)
-      .attr('y', labelBB.y)
-      .attr('height', labelBB.height)
-      .attr('width', labelBB.width);
+        // Draw the actual (dashed) lifelines in a background <g>.
 
-    // Fragments. ----------------------------------------------------------------------------------
+        this._drawLifelines(gLifelines, lifelines, y);
 
-    const fragment = fData[message.id];
-    if (fragment) {
+        // Initialize mouse event handlers.
 
-      // It ends on this message.
+        this._initMouseEvents(gLifelines, gCanvas);
 
-      this._drawFragment(gCanvas, fragment, positionsByMessageId);
+        // Scale to fit.
 
+        const bb = gContent.node().getBBox();
+        this._initZoom(gContent, bb.width, bb.height);
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Draw message into SVG canvas.
+     * @param gCanvas container.
+     * @param message message to be rendered.
+     * @param y current y position.
+     * @param actorsById actor lookup.
+     * @param positionsByMessageId x- and y-position of each message.
+     * @param messageIndex where we are in the set of messages to be rendered.
+     * @param oData occurrences info.
+     * @param fData fragments info.
+     * @private
+     */
+    _drawMessage(
+        gCanvas,
+        message,
+        y,
+        actorsById,
+        positionsByMessageId,
+        messageIndex,
+        oData,
+        fData
+    ) {
+        Common.assertNotNull(oData);
+
+        const request = message.type === 'request';
+        const fromActor = request
+            ? actorsById[message.from]
+            : actorsById[message.to];
+        const toActor = request
+            ? actorsById[message.to]
+            : actorsById[message.from];
+
+        if (!fromActor) {
+            Logger.warn(
+                `Cannot draw message ${JSON.stringify(
+                    message
+                )}: 'from' not found.`
+            );
+            return;
+        }
 
-  /**
-   * Draw a single occurrence.
-   * @param gCanvas container.
-   * @param oData occurrence data.
-   * @param positionsByMessageId map of y positions by message ID.
-   * @param actor wrapper containing lifeline ID (.id), position (.x) and name (.name).
-   * @param messageId message identifier.
-   * @private
-   */
-  _drawOccurrence(gCanvas, oData, positionsByMessageId, actor, messageId) {
+        if (!toActor) {
+            Logger.warn(
+                `Cannot draw message ${JSON.stringify(
+                    message
+                )}: 'to' not found.`
+            );
+            return;
+        }
 
-    Common.assertType(oData, 'Object');
-    Common.assertType(positionsByMessageId, 'Object');
-    Common.assertType(actor, 'Object');
-    Common.assertType(messageId, 'String');
+        // Occurrences. --------------------------------------------------------------------------------
 
-    const gOccurrences = gCanvas.select('g.asdcs-diagram-occurrences');
+        if (message.occurrence) {
+            Logger.debug(
+                `Found occurrence for ${message.name}: ${JSON.stringify(
+                    message.occurrence
+                )}`
+            );
+        }
+        const activeTo = Diagram._calcActive(oData, toActor.id);
+        this._drawOccurrence(
+            gCanvas,
+            oData,
+            positionsByMessageId,
+            fromActor,
+            message.id
+        );
+        this._drawOccurrence(
+            gCanvas,
+            oData,
+            positionsByMessageId,
+            toActor,
+            message.id
+        );
+        const activeFrom = Diagram._calcActive(oData, fromActor.id);
+
+        // Messages. -----------------------------------------------------------------------------------
+
+        const gMessages = gCanvas.select('g.asdcs-diagram-messages');
+
+        // Save positions for later.
+
+        const positions = positionsByMessageId[message.id];
+        positions.x0 = fromActor.x;
+        positions.x1 = toActor.x;
+
+        // Calculate.
+
+        const leftToRight = fromActor.x < toActor.x;
+        const loopback = message.to === message.from;
+        const x1 = this._calcMessageX(activeTo, toActor.x, true, leftToRight);
+        const x0 = loopback
+            ? x1
+            : this._calcMessageX(activeFrom, fromActor.x, false, leftToRight);
+
+        let messagePath;
+        if (loopback) {
+            // To self.
+
+            messagePath = `M${x1},${y}`;
+            messagePath = `${messagePath} L${x1 + 200},${y}`;
+            messagePath = `${messagePath} L${x1 + 200},${y + 50}`;
+            messagePath = `${messagePath} L${x1},${y + 50}`;
+        } else {
+            // Between lifelines.
 
-    const oOptions = this.options.lifelines.occurrences;
-    const oWidth = oOptions.width;
-    const oHalfWidth = oWidth / 2;
-    const oForeshortening = oOptions.foreshortening;
-    const oMarginTop = oOptions.marginTop;
-    const oMarginBottom = oOptions.marginBottom;
-    const o = oData[actor.id];
+            messagePath = `M${x0},${y}`;
+            messagePath = `${messagePath} L${x1},${y}`;
+        }
 
-    const active = Diagram._calcActive(oData, actor.id);
+        const styles = Diagram._getMessageStyles(message);
+
+        // Split message over lines.
+
+        const messageWithPrefix = `${messageIndex}. ${message.name}`;
+        const maxLines = this.options.messages.label.maxLines;
+        const wrapWords = this.options.messages.label.wrapWords;
+        const wrapLines = this.options.messages.label.wrapLines;
+        const messageLines = Common.tokenize(
+            messageWithPrefix,
+            wrapWords,
+            wrapLines,
+            maxLines
+        );
+
+        const messageTxt = this.templates.message({
+            id: message.id,
+            classes: styles.css,
+            marker: styles.marker,
+            dasharray: styles.dasharray,
+            labels: messageLines,
+            lines: maxLines,
+            path: messagePath,
+            index: messageIndex,
+            x0,
+            x1,
+            y
+        });
+
+        const messageEl = Common.txt2dom(messageTxt);
+        const gMessage = gMessages.append('g');
+        Common.dom2svg(messageEl, gMessage);
+
+        // Set the background's bounding box to that of the text,
+        // so that they fit snugly.
+
+        const labelBB = gMessage
+            .select('.asdcs-diagram-message-label')
+            .node()
+            .getBBox();
+        gMessage
+            .select('.asdcs-diagram-message-label-bg')
+            .attr('x', labelBB.x)
+            .attr('y', labelBB.y)
+            .attr('height', labelBB.height)
+            .attr('width', labelBB.width);
 
-    const x = (actor.x - oHalfWidth) + (active * oWidth);
-    const positions = positionsByMessageId[messageId];
-    const y = positions.y;
+        // Fragments. ----------------------------------------------------------------------------------
 
-    let draw = true;
-    if (o) {
+        const fragment = fData[message.id];
+        if (fragment) {
+            // It ends on this message.
 
-      if (o.start[messageId]) {
+            this._drawFragment(gCanvas, fragment, positionsByMessageId);
+        }
+    }
 
-        // Starting, but drawing nothing until we find the end.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Draw a single occurrence.
+     * @param gCanvas container.
+     * @param oData occurrence data.
+     * @param positionsByMessageId map of y positions by message ID.
+     * @param actor wrapper containing lifeline ID (.id), position (.x) and name (.name).
+     * @param messageId message identifier.
+     * @private
+     */
+    _drawOccurrence(gCanvas, oData, positionsByMessageId, actor, messageId) {
+        Common.assertType(oData, 'Object');
+        Common.assertType(positionsByMessageId, 'Object');
+        Common.assertType(actor, 'Object');
+        Common.assertType(messageId, 'String');
+
+        const gOccurrences = gCanvas.select('g.asdcs-diagram-occurrences');
+
+        const oOptions = this.options.lifelines.occurrences;
+        const oWidth = oOptions.width;
+        const oHalfWidth = oWidth / 2;
+        const oForeshortening = oOptions.foreshortening;
+        const oMarginTop = oOptions.marginTop;
+        const oMarginBottom = oOptions.marginBottom;
+        const o = oData[actor.id];
+
+        const active = Diagram._calcActive(oData, actor.id);
+
+        const x = actor.x - oHalfWidth + active * oWidth;
+        const positions = positionsByMessageId[messageId];
+        const y = positions.y;
+
+        let draw = true;
+        if (o) {
+            if (o.start[messageId]) {
+                // Starting, but drawing nothing until we find the end.
+
+                o.active.push(messageId);
+                draw = false;
+            } else if (active > 0) {
+                const startMessageId = o.stop[messageId];
+                if (startMessageId) {
+                    // OK, it ends here. Draw the occurrence box.
+
+                    o.active.pop();
+                    const foreshorteningY = active * oForeshortening;
+                    const startY = positionsByMessageId[startMessageId].y;
+                    const height =
+                        oMarginTop +
+                        oMarginBottom +
+                        (y - startY) -
+                        foreshorteningY * 2;
+                    const oProps = {
+                        x: actor.x - oHalfWidth + (active - 1) * oWidth,
+                        y: startY - oMarginTop + foreshorteningY,
+                        height,
+                        width: oWidth
+                    };
+
+                    const occurrenceTxt = this.templates.occurrence(oProps);
+                    const occurrenceEl = Common.txt2dom(occurrenceTxt);
+                    Common.dom2svg(occurrenceEl, gOccurrences.append('g'));
+                }
+                draw = false;
+            }
+        }
 
-        o.active.push(messageId);
-        draw = false;
+        if (draw) {
+            // Seems this is a singleton occurrence. We just draw a wee box around it.
+
+            const height = oMarginTop + oMarginBottom;
+            const occurrenceProperties = {
+                x,
+                y: y - oMarginTop,
+                height,
+                width: oWidth
+            };
+            const defaultTxt = this.templates.occurrence(occurrenceProperties);
+            const defaultEl = Common.txt2dom(defaultTxt);
+            Common.dom2svg(defaultEl, gOccurrences.append('g'));
+        }
+    }
 
-      } else if (active > 0) {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Draw box(es) around fragment(s).
+     * @param gCanvas container.
+     * @param fragment fragment definition, corresponding to its final (stop) message.
+     * @param positionsByMessageId message dimensions.
+     * @private
+     */
+    _drawFragment(gCanvas, fragment, positionsByMessageId) {
+        const optFragments = this.options.fragments;
+        const gFragments = gCanvas.select('g.asdcs-diagram-fragments');
+        const p1 = positionsByMessageId[fragment.stop];
+        if (p1 && fragment.start && fragment.start.length > 0) {
+            for (const start of fragment.start) {
+                const message = this.application
+                    .getModel()
+                    .getMessageById(start);
+                const bounds = this._calcFragmentBounds(
+                    message,
+                    fragment,
+                    positionsByMessageId
+                );
+                if (bounds) {
+                    const maxLines = this.options.fragments.label.maxLines;
+                    const wrapWords = this.options.fragments.label.wrapWords;
+                    const wrapLines = this.options.fragments.label.wrapLines;
+                    const lines = Common.tokenize(
+                        message.fragment.guard,
+                        wrapWords,
+                        wrapLines,
+                        maxLines
+                    );
+
+                    const params = {
+                        id: start,
+                        x: bounds.x0 - optFragments.leftMargin,
+                        y: bounds.y0 - optFragments.topMargin,
+                        height:
+                            bounds.y1 - bounds.y0 + optFragments.heightMargin,
+                        width: bounds.x1 - bounds.x0 + optFragments.widthMargin,
+                        operator: message.fragment.operator || 'alt',
+                        lines
+                    };
+
+                    const fragmentTxt = this.templates.fragment(params);
+                    const fragmentEl = Common.txt2dom(fragmentTxt);
+                    const gFragment = gFragments.append('g');
+                    Common.dom2svg(fragmentEl, gFragment);
+
+                    const labelBB = gFragment
+                        .select('.asdcs-diagram-fragment-guard')
+                        .node()
+                        .getBBox();
+                    gFragment
+                        .select('.asdcs-diagram-fragment-guard-bg')
+                        .attr('x', labelBB.x)
+                        .attr('y', labelBB.y)
+                        .attr('height', labelBB.height)
+                        .attr('width', labelBB.width);
+                } else {
+                    Logger.warn(`Bad fragment: ${JSON.stringify(fragment)}`);
+                }
+            }
+        }
+    }
 
-        const startMessageId = o.stop[messageId];
-        if (startMessageId) {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    _calcFragmentBounds(startMessage, fragment, positionsByMessageId) {
+        if (startMessage) {
+            const steps = this.application.getModel().unwrap().diagram.steps;
+            const bounds = { x0: 99999, x1: 0, y0: 99999, y1: 0 };
+            let foundStart = false;
+            let foundStop = false;
+            for (const step of steps) {
+                const message = step.message;
+                if (message) {
+                    if (message.id === startMessage.id) {
+                        foundStart = true;
+                    }
+                    if (foundStart && !foundStop) {
+                        const positions = positionsByMessageId[message.id];
+                        if (positions) {
+                            bounds.x0 = Math.min(
+                                bounds.x0,
+                                Math.min(positions.x0, positions.x1)
+                            );
+                            bounds.y0 = Math.min(bounds.y0, positions.y);
+                            bounds.x1 = Math.max(
+                                bounds.x1,
+                                Math.max(positions.x0, positions.x1)
+                            );
+                            bounds.y1 = Math.max(bounds.y1, positions.y);
+                        } else {
+                            // This probably means it hasn't been recorded yet, which is fine, because
+                            // we draw fragments from where they END.
+                            foundStop = true;
+                        }
+                    }
+
+                    if (message.id === fragment.stop) {
+                        foundStop = true;
+                    }
+                }
+            }
+            return bounds;
+        }
+        return undefined;
+    }
 
-          // OK, it ends here. Draw the occurrence box.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Draw all lifelines.
+     * @param gLifelines lifelines container.
+     * @param lifelines lifelines definitions.
+     * @param y height.
+     * @private
+     */
+    _drawLifelines(gLifelines, lifelines, y) {
+        const maxLines = this.options.lifelines.header.maxLines;
+        const wrapWords = this.options.lifelines.header.wrapWords;
+        const wrapLines = this.options.lifelines.header.wrapLines;
+
+        for (const lifeline of lifelines) {
+            const lines = Common.tokenize(
+                lifeline.actor.name,
+                wrapWords,
+                wrapLines,
+                maxLines
+            );
+            const lifelineTxt = this.templates.lifeline({
+                x: lifeline.x,
+                y0: 0,
+                y1: y,
+                lines,
+                rows: maxLines,
+                headerHeight: this.options.lifelines.header.height,
+                headerWidth: this.options.lifelines.header.width,
+                id: lifeline.actor.id
+            });
+
+            const lifelineEl = Common.txt2dom(lifelineTxt);
+            Common.dom2svg(lifelineEl, gLifelines.append('g'));
+        }
+    }
 
-          o.active.pop();
-          const foreshorteningY = active * oForeshortening;
-          const startY = positionsByMessageId[startMessageId].y;
-          const height = ((oMarginTop + oMarginBottom) + (y - startY)) - (foreshorteningY * 2);
-          const oProps = {
-            x: (actor.x - oHalfWidth) + ((active - 1) * oWidth),
-            y: ((startY - oMarginTop) + foreshorteningY),
-            height,
-            width: oWidth,
-          };
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Initialize all mouse events.
+     * @param gLifelines lifelines container.
+     * @param gCanvas top-level canvas container.
+     * @private
+     */
+    _initMouseEvents(gLifelines, gCanvas) {
+        const self = this;
+        const source = 'asdcs';
+        const origin = `${window.location.protocol}//${window.location.host}`;
+
+        let timer;
+        gLifelines
+            .selectAll('.asdcs-diagram-lifeline-selectable')
+            .on('mouseenter', function f() {
+                timer = setTimeout(() => {
+                    self.application.selectLifeline(
+                        d3.select(this.parentNode).attr('data-id')
+                    );
+                }, 150);
+            })
+            .on('mouseleave', () => {
+                clearTimeout(timer);
+                self.application.selectLifeline();
+            })
+            .on('click', function f() {
+                const id = d3.select(this.parentNode).attr('data-id');
+                window.postMessage({ source, id, type: 'lifeline' }, origin);
+            });
+
+        gLifelines
+            .selectAll('.asdcs-diagram-lifeline-heading-box')
+            .on('mouseenter', function f() {
+                timer = setTimeout(() => {
+                    self.application.selectLifeline(
+                        d3.select(this.parentNode).attr('data-id')
+                    );
+                }, 150);
+            })
+            .on('mouseleave', () => {
+                clearTimeout(timer);
+                self.application.selectLifeline();
+            })
+            .on('click', function f() {
+                const id = d3.select(this.parentNode).attr('data-id');
+                window.postMessage(
+                    { source, id, type: 'lifelineHeader' },
+                    origin
+                );
+            });
+
+        gCanvas
+            .selectAll('.asdcs-diagram-message-selectable')
+            .on('mouseenter', function f() {
+                self.events.message = { x: d3.event.pageX, y: d3.event.pageY };
+                timer = setTimeout(() => {
+                    self.application.selectMessage(
+                        d3.select(this.parentNode).attr('data-id')
+                    );
+                }, 200);
+            })
+            .on('mouseleave', () => {
+                delete self.events.message;
+                clearTimeout(timer);
+                self.application.selectMessage();
+            })
+            .on('click', function f() {
+                const id = d3.select(this.parentNode).attr('data-id');
+                window.postMessage({ source, id, type: 'message' }, origin);
+            });
+    }
 
-          const occurrenceTxt = this.templates.occurrence(oProps);
-          const occurrenceEl = Common.txt2dom(occurrenceTxt);
-          Common.dom2svg(occurrenceEl, gOccurrences.append('g'));
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get CSS classes to be applied to a message, according to whether request/response
+     * or synchronous/asynchronous.
+     * @param message message being rendered.
+     * @returns CSS class name(s).
+     * @private
+     */
+    static _getMessageStyles(message) {
+        let marker = 'asdcsDiagramArrowSolid';
+        let dasharray = '';
+        let css = 'asdcs-diagram-message';
+        if (message.type === 'request') {
+            css = `${css} asdcs-diagram-message-request`;
+        } else {
+            css = `${css} asdcs-diagram-message-response`;
+            marker = 'asdcsDiagramArrowOpen';
+            dasharray = '30, 10';
+        }
 
+        if (message.asynchronous) {
+            css = `${css} asdcs-diagram-message-asynchronous`;
+            marker = 'asdcsDiagramArrowOpen';
+        } else {
+            css = `${css} asdcs-diagram-message-synchronous`;
         }
-        draw = false;
-      }
+
+        return { css, marker, dasharray };
     }
 
-    if (draw) {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Initialize or reinitialize zoom. This sets the initial zoom in the case of
+     * a re-rendering, and initializes the eventhandling in all cases.
+     *
+     * It does some fairly risky parsing of the 'transform' attribute, assuming that it
+     * can contain scale() and translate(). But only the zoom handler and us are writing
+     * the transform values, so that's probably OK.
+     *
+     * @param gContent container.
+     * @param width diagram width.
+     * @param height diagram height.
+     * @private
+     */
+    _initZoom(gContent, width, height) {
+        const zoomed = function zoomed() {
+            if (!this.initialTransformX && !this.initialTransformY) {
+                this.initialTransformX = d3.event.transform.x;
+                this.initialTransformY = d3.event.transform.y;
+            }
 
-      // Seems this is a singleton occurrence. We just draw a wee box around it.
+            gContent.attr(
+                'transform',
+                `translate(${d3.event.transform.x -
+                    this.initialTransformX}, ${d3.event.transform.y -
+                    this.initialTransformY})scale(${d3.event.transform.k}, ${
+                    d3.event.transform.k
+                })`
+            );
+        };
+
+        const viewWidth = this.state.width || this.options.svg.width;
+        const viewHeight = this.state.height || this.options.svg.height;
+        const scaleMinimum = this.options.svg.scale.minimum;
+        const scaleWidth = viewWidth / width;
+        const scaleHeight = viewHeight / height;
+
+        let scale = scaleMinimum;
+        if (this.options.svg.scale.width) {
+            scale = Math.max(scale, scaleWidth);
+        }
+        if (this.options.svg.scale.height) {
+            scale = Math.min(scale, scaleHeight);
+        }
 
-      const height = (oMarginTop + oMarginBottom);
-      const occurrenceProperties = { x, y: y - oMarginTop, height, width: oWidth };
-      const defaultTxt = this.templates.occurrence(occurrenceProperties);
-      const defaultEl = Common.txt2dom(defaultTxt);
-      Common.dom2svg(defaultEl, gOccurrences.append('g'));
-    }
+        scale = Math.max(scale, scaleMinimum);
 
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Draw box(es) around fragment(s).
-   * @param gCanvas container.
-   * @param fragment fragment definition, corresponding to its final (stop) message.
-   * @param positionsByMessageId message dimensions.
-   * @private
-   */
-  _drawFragment(gCanvas, fragment, positionsByMessageId) {
-
-    const optFragments = this.options.fragments;
-    const gFragments = gCanvas.select('g.asdcs-diagram-fragments');
-    const p1 = positionsByMessageId[fragment.stop];
-    if (p1 && fragment.start && fragment.start.length > 0) {
-
-      for (const start of fragment.start) {
-
-        const message = this.application.getModel().getMessageById(start);
-        const bounds = this._calcFragmentBounds(message, fragment, positionsByMessageId);
-        if (bounds) {
-
-          const maxLines = this.options.fragments.label.maxLines;
-          const wrapWords = this.options.fragments.label.wrapWords;
-          const wrapLines = this.options.fragments.label.wrapLines;
-          const lines = Common.tokenize(message.fragment.guard, wrapWords, wrapLines, maxLines);
-
-          const params = {
-            id: start,
-            x: bounds.x0 - optFragments.leftMargin,
-            y: bounds.y0 - optFragments.topMargin,
-            height: (bounds.y1 - bounds.y0) + optFragments.heightMargin,
-            width: (bounds.x1 - bounds.x0) + optFragments.widthMargin,
-            operator: (message.fragment.operator || 'alt'),
-            lines,
-          };
-
-          const fragmentTxt = this.templates.fragment(params);
-          const fragmentEl = Common.txt2dom(fragmentTxt);
-          const gFragment = gFragments.append('g');
-          Common.dom2svg(fragmentEl, gFragment);
-
-          const labelBB = gFragment.select('.asdcs-diagram-fragment-guard').node().getBBox();
-          gFragment.select('.asdcs-diagram-fragment-guard-bg')
-            .attr('x', labelBB.x)
-            .attr('y', labelBB.y)
-            .attr('height', labelBB.height)
-            .attr('width', labelBB.width);
+        let translate = [0, 0];
+        if (this.savedTransform) {
+            const s = this.savedTransform;
+            const scaleStart = s.indexOf('scale(');
+            if (scaleStart !== -1) {
+                scale = parseFloat(s.substring(scaleStart + 6, s.length - 1));
+            }
+            const translateStart = s.indexOf('translate(');
+            if (translateStart !== -1) {
+                const spec = s.substring(
+                    translateStart + 10,
+                    s.indexOf(')', translateStart)
+                );
+                const tokens = spec.split(',');
+                translate = [parseFloat(tokens[0]), parseFloat(tokens[1])];
+            }
 
+            gContent.attr('transform', this.savedTransform);
         } else {
-          Logger.warn(`Bad fragment: ${JSON.stringify(fragment)}`);
+            gContent.attr('transform', `scale(${scale})`);
         }
-      }
-    }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  _calcFragmentBounds(startMessage, fragment, positionsByMessageId) {
-    if (startMessage) {
-      const steps = this.application.getModel().unwrap().diagram.steps;
-      const bounds = { x0: 99999, x1: 0, y0: 99999, y1: 0 };
-      let foundStart = false;
-      let foundStop = false;
-      for (const step of steps) {
-        const message = step.message;
-        if (message) {
-          if (message.id === startMessage.id) {
-            foundStart = true;
-          }
-          if (foundStart && !foundStop) {
-            const positions = positionsByMessageId[message.id];
-            if (positions) {
-              bounds.x0 = Math.min(bounds.x0, Math.min(positions.x0, positions.x1));
-              bounds.y0 = Math.min(bounds.y0, positions.y);
-              bounds.x1 = Math.max(bounds.x1, Math.max(positions.x0, positions.x1));
-              bounds.y1 = Math.max(bounds.y1, positions.y);
-            } else {
-              // This probably means it hasn't been recorded yet, which is fine, because
-              // we draw fragments from where they END.
-              foundStop = true;
-            }
-          }
 
-          if (message.id === fragment.stop) {
-            foundStop = true;
-          }
-        }
-      }
-      return bounds;
-    }
-    return undefined;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Draw all lifelines.
-   * @param gLifelines lifelines container.
-   * @param lifelines lifelines definitions.
-   * @param y height.
-   * @private
-   */
-  _drawLifelines(gLifelines, lifelines, y) {
-
-    const maxLines = this.options.lifelines.header.maxLines;
-    const wrapWords = this.options.lifelines.header.wrapWords;
-    const wrapLines = this.options.lifelines.header.wrapLines;
-
-    for (const lifeline of lifelines) {
-      const lines = Common.tokenize(lifeline.actor.name, wrapWords, wrapLines, maxLines);
-      const lifelineTxt = this.templates.lifeline({
-        x: lifeline.x,
-        y0: 0,
-        y1: y,
-        lines,
-        rows: maxLines,
-        headerHeight: this.options.lifelines.header.height,
-        headerWidth: this.options.lifelines.header.width,
-        id: lifeline.actor.id,
-      });
-
-      const lifelineEl = Common.txt2dom(lifelineTxt);
-      Common.dom2svg(lifelineEl, gLifelines.append('g'));
-    }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Initialize all mouse events.
-   * @param gLifelines lifelines container.
-   * @param gCanvas top-level canvas container.
-   * @private
-   */
-  _initMouseEvents(gLifelines, gCanvas) {
-
-    const self = this;
-    const source = 'asdcs';
-    const origin = `${window.location.protocol}//${window.location.host}`;
-
-    let timer;
-    gLifelines.selectAll('.asdcs-diagram-lifeline-selectable')
-      .on('mouseenter', function f() {
-        timer = setTimeout(() => {
-          self.application.selectLifeline(d3.select(this.parentNode).attr('data-id'));
-        }, 150);
-      })
-      .on('mouseleave', () => {
-        clearTimeout(timer);
-        self.application.selectLifeline();
-      })
-      .on('click', function f() {
-        const id = d3.select(this.parentNode).attr('data-id');
-        window.postMessage({ source, id, type: 'lifeline' }, origin);
-      });
-
-    gLifelines.selectAll('.asdcs-diagram-lifeline-heading-box')
-      .on('mouseenter', function f() {
-        timer = setTimeout(() => {
-          self.application.selectLifeline(d3.select(this.parentNode).attr('data-id'));
-        }, 150);
-      })
-      .on('mouseleave', () => {
-        clearTimeout(timer);
-        self.application.selectLifeline();
-      })
-      .on('click', function f() {
-        const id = d3.select(this.parentNode).attr('data-id');
-        window.postMessage({ source, id, type: 'lifelineHeader' }, origin);
-      });
-
-    gCanvas.selectAll('.asdcs-diagram-message-selectable')
-      .on('mouseenter', function f() {
-        self.events.message = { x: d3.event.pageX, y: d3.event.pageY };
-        timer = setTimeout(() => {
-          self.application.selectMessage(d3.select(this.parentNode).attr('data-id'));
-        }, 200);
-      })
-      .on('mouseleave', () => {
-        delete self.events.message;
-        clearTimeout(timer);
-        self.application.selectMessage();
-      })
-      .on('click', function f() {
-        const id = d3.select(this.parentNode).attr('data-id');
-        window.postMessage({ source, id, type: 'message' }, origin);
-      });
-
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get CSS classes to be applied to a message, according to whether request/response
-   * or synchronous/asynchronous.
-   * @param message message being rendered.
-   * @returns CSS class name(s).
-   * @private
-   */
-  static _getMessageStyles(message) {
-
-    let marker = 'asdcsDiagramArrowSolid';
-    let dasharray = '';
-    let css = 'asdcs-diagram-message';
-    if (message.type === 'request') {
-      css = `${css} asdcs-diagram-message-request`;
-    } else {
-      css = `${css} asdcs-diagram-message-response`;
-      marker = 'asdcsDiagramArrowOpen';
-      dasharray = '30, 10';
-    }
+        const zoom = d3.zoom().on('zoom', zoomed);
 
-    if (message.asynchronous) {
-      css = `${css} asdcs-diagram-message-asynchronous`;
-      marker = 'asdcsDiagramArrowOpen';
-    } else {
-      css = `${css} asdcs-diagram-message-synchronous`;
-    }
+        this.svg.call(zoom);
+        this.svg.call(zoom.scaleBy, scale);
 
-    return { css, marker, dasharray };
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Initialize or reinitialize zoom. This sets the initial zoom in the case of
-   * a re-rendering, and initializes the eventhandling in all cases.
-   *
-   * It does some fairly risky parsing of the 'transform' attribute, assuming that it
-   * can contain scale() and translate(). But only the zoom handler and us are writing
-   * the transform values, so that's probably OK.
-   *
-   * @param gContent container.
-   * @param width diagram width.
-   * @param height diagram height.
-   * @private
-   */
-  _initZoom(gContent, width, height) {
-
-    const zoomed = function zoomed() {
-      if (!this.initialTransformX && !this.initialTransformY) {
-        this.initialTransformX = d3.event.transform.x;
-        this.initialTransformY = d3.event.transform.y;
-      }
-
-      gContent.attr('transform',
-                               `translate(${d3.event.transform.x - this.initialTransformX}, ${d3.event.transform.y
-                               - this.initialTransformY})scale(${d3.event.transform.k}, ${d3.event.transform.k})`);
-    };
-
-    const viewWidth = this.state.width || this.options.svg.width;
-    const viewHeight = this.state.height || this.options.svg.height;
-    const scaleMinimum = this.options.svg.scale.minimum;
-    const scaleWidth = viewWidth / width;
-    const scaleHeight = viewHeight / height;
-
-    let scale = scaleMinimum;
-    if (this.options.svg.scale.width) {
-      scale = Math.max(scale, scaleWidth);
-    }
-    if (this.options.svg.scale.height) {
-      scale = Math.min(scale, scaleHeight);
+        gContent.attr(
+            'transform',
+            `translate(${translate[0]}, ${translate[1]})`
+        );
+        gContent.attr('transform', `scale(${scale})`);
     }
 
-    scale = Math.max(scale, scaleMinimum);
-
-    let translate = [0, 0];
-    if (this.savedTransform) {
-      const s = this.savedTransform;
-      const scaleStart = s.indexOf('scale(');
-      if (scaleStart !== -1) {
-        scale = parseFloat(s.substring(scaleStart + 6, s.length - 1));
-      }
-      const translateStart = s.indexOf('translate(');
-      if (translateStart !== -1) {
-        const spec = s.substring(translateStart + 10, s.indexOf(')', translateStart));
-        const tokens = spec.split(',');
-        translate = [parseFloat(tokens[0]), parseFloat(tokens[1])];
-      }
-
-      gContent.attr('transform', this.savedTransform);
-    } else {
-      gContent.attr('transform', `scale(${scale})`);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Hide from the linter the fact that we're modifying the lifeline.
+     * @param lifeline to be updated with X position.
+     * @param x X position.
+     * @private
+     */
+    static _processLifeline(lifeline, x) {
+        const actor = lifeline;
+        actor.id = actor.id || actor.name;
+        actor.x = x;
     }
 
-    const zoom = d3.zoom()
-      .on('zoom', zoomed);
-
-    this.svg.call(zoom);
-    this.svg.call(zoom.scaleBy, scale);
-
-    gContent.attr('transform', `translate(${translate[0]}, ${translate[1]})`);
-    gContent.attr('transform', `scale(${scale})`);
-
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Hide from the linter the fact that we're modifying the lifeline.
-   * @param lifeline to be updated with X position.
-   * @param x X position.
-   * @private
-   */
-  static _processLifeline(lifeline, x) {
-    const actor = lifeline;
-    actor.id = actor.id || actor.name;
-    actor.x = x;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Derive active occurrences for lifeline.
-   * @param oData occurrences data.
-   * @param lifelineId lifeline to be analyzed.
-   * @returns {number}
-   * @private
-   */
-  static _calcActive(oData, lifelineId) {
-    const o = oData[lifelineId];
-    let active = 0;
-    if (o && o.active) {
-      active = o.active.length;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Derive active occurrences for lifeline.
+     * @param oData occurrences data.
+     * @param lifelineId lifeline to be analyzed.
+     * @returns {number}
+     * @private
+     */
+    static _calcActive(oData, lifelineId) {
+        const o = oData[lifelineId];
+        let active = 0;
+        if (o && o.active) {
+            active = o.active.length;
+        }
+        return active;
     }
-    return active;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Derive the X position of an occurrence on a lifeline, taking into account how
-   * many occurrences are active.
-   * @param active active count.
-   * @param x lifeline X position; basis for offset.
-   * @param arrow whether this is the arrow (to) end.
-   * @param leftToRight whether this message goes left-to-right.
-   * @returns {*} calculated X position for occurrence left-hand side.
-   * @private
-   */
-  _calcMessageX(active, x, arrow, leftToRight) {
-    const width = this.options.lifelines.occurrences.width;
-    const halfWidth = width / 2;
-    const active0 = Math.max(0, active - 1);
-    let calculated = x + (active0 * width);
-    if (arrow) {
-      // End (ARROW).
-      if (leftToRight) {
-        calculated -= halfWidth;
-      } else {
-        calculated += halfWidth;
-      }
-    } else {
-      // Start (NOT ARROW).
-      if (leftToRight) {
-        calculated += halfWidth;
-      } else {
-        calculated -= halfWidth;
-      }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Derive the X position of an occurrence on a lifeline, taking into account how
+     * many occurrences are active.
+     * @param active active count.
+     * @param x lifeline X position; basis for offset.
+     * @param arrow whether this is the arrow (to) end.
+     * @param leftToRight whether this message goes left-to-right.
+     * @returns {*} calculated X position for occurrence left-hand side.
+     * @private
+     */
+    _calcMessageX(active, x, arrow, leftToRight) {
+        const width = this.options.lifelines.occurrences.width;
+        const halfWidth = width / 2;
+        const active0 = Math.max(0, active - 1);
+        let calculated = x + active0 * width;
+        if (arrow) {
+            // End (ARROW).
+            if (leftToRight) {
+                calculated -= halfWidth;
+            } else {
+                calculated += halfWidth;
+            }
+        } else {
+            // Start (NOT ARROW).
+            if (leftToRight) {
+                calculated += halfWidth;
+            } else {
+                calculated -= halfWidth;
+            }
+        }
+
+        return calculated;
     }
 
-    return calculated;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show popup upon hovering over a messages that has associated notes.
-   * @param id
-   * @private
-   */
-  _showNotesPopup(id) {
-    if (this.popup) {
-      if (id) {
-        const message = this.application.getModel().getMessageById(id);
-        if (message && message.notes && message.notes.length > 0 && this.events.message) {
-          this.popup.setState({
-            visible: true,
-            left: this.events.message.x - 50,
-            top: this.events.message.y + 20,
-            notes: message.notes[0],
-          });
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show popup upon hovering over a messages that has associated notes.
+     * @param id
+     * @private
+     */
+    _showNotesPopup(id) {
+        if (this.popup) {
+            if (id) {
+                const message = this.application.getModel().getMessageById(id);
+                if (
+                    message &&
+                    message.notes &&
+                    message.notes.length > 0 &&
+                    this.events.message
+                ) {
+                    this.popup.setState({
+                        visible: true,
+                        left: this.events.message.x - 50,
+                        top: this.events.message.y + 20,
+                        notes: message.notes[0]
+                    });
+                }
+            } else {
+                this.popup.setState({ visible: false, notes: '' });
+            }
         }
-      } else {
-        this.popup.setState({ visible: false, notes: '' });
-      }
     }
-  }
 }
 
-
 Diagram.propTypes = {
-  application: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired
 };
 
 export default Diagram;
index 8f8f859..a2a6582 100644 (file)
@@ -25,85 +25,81 @@ import iconEdit from '../../../../../../../../res/ecomp/asdc/sequencer/sprites/i
  * @constructor
  */
 class Popup extends React.Component {
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct react view.
-   * @param props element properties (of which there are none).
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.state = {
-      top: 0,
-      left: 0,
-      visible: false,
-      notes: '',
-    };
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render view.
-   * @returns {XML}
-   */
-  render() {
-
-    // Build CSS + styles to position and configure popup.
-
-    let top = this.state.top;
-    let left = this.state.left;
-
-    const popupHeight = 200;
-    const popupWidth = 320;
-
-    let auxCssVertical = 'top';
-    let auxCssHorizontal = 'left';
-
-    if (this.state.top > (window.innerHeight - popupHeight)) {
-      top -= (popupHeight + 50);
-      auxCssVertical = 'bottom';
-    }
-
-    if (this.state.left > (window.innerWidth - popupWidth)) {
-      left -= (popupWidth - 80);
-      auxCssHorizontal = 'right';
-    }
-
-    const auxCss = `asdcs-diagram-popup-${auxCssVertical}${auxCssHorizontal}`;
-    const styles = {
-      top,
-      left,
-      display: (this.state.visible ? 'block' : 'none'),
-    };
-
-    // Render element.
-
-    let notes = this.state.notes || '';
-    if (notes.length > 255) {
-      notes = notes.substring(0, 255);
-      notes = `${notes} ...`;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct react view.
+     * @param props element properties (of which there are none).
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.state = {
+            top: 0,
+            left: 0,
+            visible: false,
+            notes: ''
+        };
     }
 
-    return (
-      <div className={`asdcs-diagram-popup ${auxCss}`} style={styles}>
-        <div className="asdcs-diagram-popup-header">Notes</div>
-        <div className="asdcs-diagram-popup-body">
-          <div className="asdcs-icon-popup">
-            <Icon glyph={iconEdit} />
-          </div>
-          <div className="asdcs-diagram-notes">
-            <div className="asdcs-diagram-note">
-              {notes}
+    // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render view.
+     * @returns {XML}
+     */
+    render() {
+        // Build CSS + styles to position and configure popup.
+
+        let top = this.state.top;
+        let left = this.state.left;
+
+        const popupHeight = 200;
+        const popupWidth = 320;
+
+        let auxCssVertical = 'top';
+        let auxCssHorizontal = 'left';
+
+        if (this.state.top > window.innerHeight - popupHeight) {
+            top -= popupHeight + 50;
+            auxCssVertical = 'bottom';
+        }
+
+        if (this.state.left > window.innerWidth - popupWidth) {
+            left -= popupWidth - 80;
+            auxCssHorizontal = 'right';
+        }
+
+        const auxCss = `asdcs-diagram-popup-${auxCssVertical}${auxCssHorizontal}`;
+        const styles = {
+            top,
+            left,
+            display: this.state.visible ? 'block' : 'none'
+        };
+
+        // Render element.
+
+        let notes = this.state.notes || '';
+        if (notes.length > 255) {
+            notes = notes.substring(0, 255);
+            notes = `${notes} ...`;
+        }
+
+        return (
+            <div className={`asdcs-diagram-popup ${auxCss}`} style={styles}>
+                <div className="asdcs-diagram-popup-header">Notes</div>
+                <div className="asdcs-diagram-popup-body">
+                    <div className="asdcs-icon-popup">
+                        <Icon glyph={iconEdit} />
+                    </div>
+                    <div className="asdcs-diagram-notes">
+                        <div className="asdcs-diagram-note">{notes}</div>
+                    </div>
+                </div>
+                <div className="asdcs-diagram-popup-footer" />
             </div>
-          </div>
-        </div>
-        <div className="asdcs-diagram-popup-footer"></div>
-      </div>
-    );
-  }
+        );
+    }
 }
 
 export default Popup;
index d48ef3b..96a7099 100644 (file)
@@ -28,211 +28,216 @@ import iconClose from '../../../../../../res/ecomp/asdc/sequencer/sprites/icons/
  * configured, shown and hidden as required.
  */
 class Dialog extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        this.MODE = {
+            INFO: {
+                icon: 'asdcs-icon-info',
+                heading: 'Information'
+            },
+            ERROR: {
+                icon: 'asdcs-icon-exclaim',
+                heading: 'Error'
+            },
+            EDIT: {
+                icon: 'asdcs-icon-edit',
+                heading: 'Edit',
+                edit: true,
+                confirm: true
+            },
+            CONFIRM: {
+                icon: 'asdcs-icon-question',
+                heading: 'Confirm',
+                confirm: true
+            }
+        };
+
+        this.state = {
+            mode: this.MODE.INFO,
+            message: '',
+            text: '',
+            visible: false
+        };
+
+        // Bindings.
+
+        this.onClickOK = this.onClickOK.bind(this);
+        this.onClickCancel = this.onClickCancel.bind(this);
+        this.onChangeText = this.onChangeText.bind(this);
+        this.showConfirmDialog = this.showConfirmDialog.bind(this);
+        this.showInfoDialog = this.showInfoDialog.bind(this);
+        this.showEditDialog = this.showEditDialog.bind(this);
+        this.showErrorDialog = this.showErrorDialog.bind(this);
+        this.showDialog = this.showDialog.bind(this);
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show info dialog.
+     * @param message info message.
+     */
+    showInfoDialog(message) {
+        this.showDialog(this.MODE.INFO, { message });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show error dialog.
+     * @param message error message.
+     */
+    showErrorDialog(message) {
+        this.showDialog(this.MODE.ERROR, { message });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show edit dialog.
+     * @param message dialog message.
+     * @param text current edit text.
+     * @param callback callback function to be invoked on OK.
+     */
+    showEditDialog(message, text, callback) {
+        this.showDialog(this.MODE.EDIT, { message, text, callback });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show confirmation dialog.
+     * @param message dialog message.
+     * @param callback callback function to be invoked on OK.
+     */
+    showConfirmDialog(message, callback) {
+        this.showDialog(this.MODE.CONFIRM, { message, callback });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle buttonclick.
+     */
+    onClickOK() {
+        this.props.application.hideOverlay();
+        this.setState({ visible: false });
+        if (this.callback) {
+            // So far the only thing we can return is edit text, but send it back
+            // as properties to allow for future return values.
+
+            this.callback({ text: this.state.text });
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle buttonclick.
+     */
+    onClickCancel() {
+        this.props.application.hideOverlay();
+        this.setState({ visible: false });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle text changes.
+     * @param event update event.
+     */
+    onChangeText(event) {
+        this.setState({ text: event.target.value });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show dialog in specified configuration.
+     * @param mode dialog mode.
+     * @param args dialog parameters, varying slightly by dialog type.
+     * @private
+     */
+    showDialog(mode, args) {
+        this.props.application.showOverlay();
+        this.callback = args.callback;
+        this.setState({
+            mode,
+            visible: true,
+            message: args.message || '',
+            text: args.text || ''
+        });
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct view.
-   */
-  constructor(props, context) {
-
-    super(props, context);
-
-    this.MODE = {
-      INFO: {
-        icon: 'asdcs-icon-info',
-        heading: 'Information',
-      },
-      ERROR: {
-        icon: 'asdcs-icon-exclaim',
-        heading: 'Error',
-      },
-      EDIT: {
-        icon: 'asdcs-icon-edit',
-        heading: 'Edit',
-        edit: true,
-        confirm: true,
-      },
-      CONFIRM: {
-        icon: 'asdcs-icon-question',
-        heading: 'Confirm',
-        confirm: true,
-      },
-    };
-
-    this.state = {
-      mode: this.MODE.INFO,
-      message: '',
-      text: '',
-      visible: false,
-    };
-
-    // Bindings.
-
-    this.onClickOK = this.onClickOK.bind(this);
-    this.onClickCancel = this.onClickCancel.bind(this);
-    this.onChangeText = this.onChangeText.bind(this);
-    this.showConfirmDialog = this.showConfirmDialog.bind(this);
-    this.showInfoDialog = this.showInfoDialog.bind(this);
-    this.showEditDialog = this.showEditDialog.bind(this);
-    this.showErrorDialog = this.showErrorDialog.bind(this);
-    this.showDialog = this.showDialog.bind(this);
-
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show info dialog.
-   * @param message info message.
-   */
-  showInfoDialog(message) {
-    this.showDialog(this.MODE.INFO, { message });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show error dialog.
-   * @param message error message.
-   */
-  showErrorDialog(message) {
-    this.showDialog(this.MODE.ERROR, { message });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show edit dialog.
-   * @param message dialog message.
-   * @param text current edit text.
-   * @param callback callback function to be invoked on OK.
-   */
-  showEditDialog(message, text, callback) {
-    this.showDialog(this.MODE.EDIT, { message, text, callback });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show confirmation dialog.
-   * @param message dialog message.
-   * @param callback callback function to be invoked on OK.
-   */
-  showConfirmDialog(message, callback) {
-    this.showDialog(this.MODE.CONFIRM, { message, callback });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle buttonclick.
-   */
-  onClickOK() {
-    this.props.application.hideOverlay();
-    this.setState({ visible: false });
-    if (this.callback) {
-
-      // So far the only thing we can return is edit text, but send it back
-      // as properties to allow for future return values.
-
-      this.callback({ text: this.state.text });
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render dialog into the page, initially hidden.
+     */
+    render() {
+        const dialogClass = this.state.visible ? '' : 'asdcs-hidden';
+        const cancelClass = this.callback ? '' : 'asdcs-hidden';
+        const textClass =
+            this.state.mode === this.MODE.EDIT ? '' : 'asdcs-hidden';
+
+        return (
+            <div className={`asdcs-dialog ${dialogClass}`}>
+                <div className="asdcs-dialog-header">
+                    {this.state.mode.heading}
+                </div>
+                <div
+                    className="asdcs-dialog-close"
+                    onClick={this.onClickCancel}>
+                    <Icon
+                        glyph={iconClose}
+                        className={this.MODE.CONFIRM.icon}
+                    />
+                </div>
+                <div className={`asdcs-dialog-icon ${this.state.mode.icon}`}>
+                    <Icon
+                        glyph={iconQuestion}
+                        className={this.MODE.CONFIRM.icon}
+                    />
+                    <Icon
+                        glyph={iconExclaim}
+                        className={this.MODE.ERROR.icon}
+                    />
+                    <Icon glyph={iconInfo} className={this.MODE.INFO.icon} />
+                    <Icon glyph={iconEdit} className={this.MODE.EDIT.icon} />
+                </div>
+                <div className="asdcs-dialog-message">{this.state.message}</div>
+                <div className={`asdcs-dialog-text ${textClass}`}>
+                    <textarea
+                        maxLength="255"
+                        value={this.state.text}
+                        onChange={this.onChangeText}
+                    />
+                </div>
+                <div className="asdcs-dialog-buttonbar">
+                    <button
+                        className={`asdcs-dialog-button-cancel ${cancelClass}`}
+                        onClick={this.onClickCancel}>
+                        Cancel
+                    </button>
+                    <button
+                        className="asdcs-dialog-button-ok"
+                        onClick={this.onClickOK}>
+                        OK
+                    </button>
+                </div>
+            </div>
+        );
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle buttonclick.
-   */
-  onClickCancel() {
-    this.props.application.hideOverlay();
-    this.setState({ visible: false });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle text changes.
-   * @param event update event.
-   */
-  onChangeText(event) {
-    this.setState({ text: event.target.value });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show dialog in specified configuration.
-   * @param mode dialog mode.
-   * @param args dialog parameters, varying slightly by dialog type.
-   * @private
-   */
-  showDialog(mode, args) {
-    this.props.application.showOverlay();
-    this.callback = args.callback;
-    this.setState({
-      mode,
-      visible: true,
-      message: args.message || '',
-      text: args.text || '',
-    });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render dialog into the page, initially hidden.
-   */
-  render() {
-
-    const dialogClass = (this.state.visible) ? '' : 'asdcs-hidden';
-    const cancelClass = (this.callback) ? '' : 'asdcs-hidden';
-    const textClass = (this.state.mode === this.MODE.EDIT) ? '' : 'asdcs-hidden';
-
-    return (
-      <div className={`asdcs-dialog ${dialogClass}`}>
-        <div className="asdcs-dialog-header">{this.state.mode.heading}</div>
-        <div className="asdcs-dialog-close" onClick={this.onClickCancel} >
-          <Icon glyph={iconClose} className={this.MODE.CONFIRM.icon} />
-        </div>
-        <div className={`asdcs-dialog-icon ${this.state.mode.icon}`}>
-          <Icon glyph={iconQuestion} className={this.MODE.CONFIRM.icon} />
-          <Icon glyph={iconExclaim} className={this.MODE.ERROR.icon} />
-          <Icon glyph={iconInfo} className={this.MODE.INFO.icon} />
-          <Icon glyph={iconEdit} className={this.MODE.EDIT.icon} />
-        </div>
-        <div className="asdcs-dialog-message">
-          {this.state.message}
-        </div>
-        <div className={`asdcs-dialog-text ${textClass}`}>
-          <textarea
-            maxLength="255"
-            value={this.state.text}
-            onChange={this.onChangeText}
-          />
-        </div>
-        <div className="asdcs-dialog-buttonbar">
-          <button
-            className={`asdcs-dialog-button-cancel ${cancelClass}`}
-            onClick={this.onClickCancel}
-          >
-            Cancel
-          </button>
-          <button
-            className="asdcs-dialog-button-ok"
-            onClick={this.onClickOK}
-          >
-            OK
-          </button>
-        </div>
-      </div>
-    );
-  }
 }
 
 Dialog.propTypes = {
-  application: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired
 };
 
 export default Dialog;
index 00c8f7c..087bc80 100644 (file)
@@ -26,149 +26,147 @@ import Source from './components/source/Source';
  * Editor view, aggregating the designer, the code editor, the toolbar.
  */
 class Editor extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Construct React view.
+     * @param props properties.
+     * @param context context.
+     */
+    constructor(props, context) {
+        super(props, context);
 
-  /**
-   * Construct React view.
-   * @param props properties.
-   * @param context context.
-   */
-  constructor(props, context) {
-    super(props, context);
+        this.application = Common.assertNotNull(props.application);
+        this.demo = this.application.getOptions().demo;
 
-    this.application = Common.assertNotNull(props.application);
-    this.demo = this.application.getOptions().demo;
+        // Bindings.
 
-    // Bindings.
+        this.selectMessage = this.selectMessage.bind(this);
+        this.selectLifeline = this.selectLifeline.bind(this);
 
-    this.selectMessage = this.selectMessage.bind(this);
-    this.selectLifeline = this.selectLifeline.bind(this);
-
-    this.onMouseDown = this.onMouseDown.bind(this);
-    this.onMouseUp = this.onMouseUp.bind(this);
-    this.onMouseMove = this.onMouseMove.bind(this);
-  }
+        this.onMouseDown = this.onMouseDown.bind(this);
+        this.onMouseUp = this.onMouseUp.bind(this);
+        this.onMouseMove = this.onMouseMove.bind(this);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Select message by ID.
-   * @param id message ID.
-   */
-  selectMessage(id) {
-    if (this.designer) {
-      this.designer.selectMessage(id);
+    /**
+     * Select message by ID.
+     * @param id message ID.
+     */
+    selectMessage(id) {
+        if (this.designer) {
+            this.designer.selectMessage(id);
+        }
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Select lifeline by ID.
-   * @param id lifeline ID.
-   */
-  selectLifeline(id) {
-    if (this.designer) {
-      this.designer.selectLifeline(id);
+    /**
+     * Select lifeline by ID.
+     * @param id lifeline ID.
+     */
+    selectLifeline(id) {
+        if (this.designer) {
+            this.designer.selectLifeline(id);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Record that we're dragging.
-   */
-  onMouseDown() {
-    if (this.editor) {
-      this.resize = {
-        initialWidth: this.editor.offsetWidth,
-        initialPageX: undefined,
-      };
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Record that we're dragging.
+     */
+    onMouseDown() {
+        if (this.editor) {
+            this.resize = {
+                initialWidth: this.editor.offsetWidth,
+                initialPageX: undefined
+            };
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Record that we're not dragging.
-   */
-  onMouseUp() {
-    this.resize = undefined;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Record mouse movement.
-   */
-  onMouseMove(event) {
-    if (this.resize) {
-      if (this.editor) {
-        if (this.resize.initialPageX) {
-          const deltaX = event.pageX - this.resize.initialPageX;
-          const newWidth = this.resize.initialWidth + deltaX;
-          const newWidthBounded = Math.min(800, Math.max(400, newWidth));
-          this.editor.style.width = `${newWidthBounded}px`;
-        } else {
-          this.resize.initialPageX = event.pageX;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Record that we're not dragging.
+     */
+    onMouseUp() {
+        this.resize = undefined;
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Record mouse movement.
+     */
+    onMouseMove(event) {
+        if (this.resize) {
+            if (this.editor) {
+                if (this.resize.initialPageX) {
+                    const deltaX = event.pageX - this.resize.initialPageX;
+                    const newWidth = this.resize.initialWidth + deltaX;
+                    const newWidthBounded = Math.min(
+                        800,
+                        Math.max(400, newWidth)
+                    );
+                    this.editor.style.width = `${newWidthBounded}px`;
+                } else {
+                    this.resize.initialPageX = event.pageX;
+                }
+            }
         }
-      }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render editor.
-   */
-  render() {
-
-    Logger.info('Editor.jsx - render()');
-
-    return (
-
-      <div
-        className="asdcs-editor"
-        ref={(r) => { this.editor = r; }}
-      >
-
-        <Toolbar application={this.props.application} editor={this} />
-
-        <div className="asdcs-editor-content">
-          <Source application={this.props.application} />
-          <Designer
-            application={this.props.application}
-            ref={(r) => {
-              if (r) {
-                this.designer = r.getDecoratedComponentInstance();
-              } else {
-                this.designer = null;
-              }
-            }}
-          />
-        </div>
-
-        <div className="asdcs-editor-statusbar">
-          <div className="asdcs-editor-status"></div>
-          <div className="asdcs-editor-validation"></div>
-        </div>
-
-        <div
-          className="asdcs-editor-resize-handle"
-          onMouseDown={this.onMouseDown}
-          onMouseUp={this.onMouseUp}
-        >
-        </div>
-      </div>
-    );
-  }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render editor.
+     */
+    render() {
+        Logger.info('Editor.jsx - render()');
+
+        return (
+            <div
+                className="asdcs-editor"
+                ref={r => {
+                    this.editor = r;
+                }}>
+                <Toolbar application={this.props.application} editor={this} />
+
+                <div className="asdcs-editor-content">
+                    <Source application={this.props.application} />
+                    <Designer
+                        application={this.props.application}
+                        ref={r => {
+                            if (r) {
+                                this.designer = r.getDecoratedComponentInstance();
+                            } else {
+                                this.designer = null;
+                            }
+                        }}
+                    />
+                </div>
+
+                <div className="asdcs-editor-statusbar">
+                    <div className="asdcs-editor-status" />
+                    <div className="asdcs-editor-validation" />
+                </div>
+
+                <div
+                    className="asdcs-editor-resize-handle"
+                    onMouseDown={this.onMouseDown}
+                    onMouseUp={this.onMouseUp}
+                />
+            </div>
+        );
+    }
 }
 
 /** Element properties. */
 Editor.propTypes = {
-  application: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired
 };
 
 export default Editor;
-
index c67c68e..09e321d 100644 (file)
@@ -35,369 +35,383 @@ import iconCollapsed from '../../../../../../../../res/ecomp/asdc/sequencer/spri
  * LHS design wid` view.
  */
 class Designer extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        Logger.noop();
+
+        this.application = Common.assertNotNull(props.application);
+
+        this.state = {
+            lifelinesExpanded: false,
+            messagesExpanded: true,
+            activeLifelineId: undefined,
+            activeMessageId: undefined
+        };
+
+        // Bind this.
+
+        this.onToggle = this.onToggle.bind(this);
+        this.onMouseEnterLifeline = this.onMouseEnterLifeline.bind(this);
+        this.onMouseLeaveLifeline = this.onMouseLeaveLifeline.bind(this);
+        this.onMouseEnterMessage = this.onMouseEnterMessage.bind(this);
+        this.onMouseLeaveMessage = this.onMouseLeaveMessage.bind(this);
+
+        this.addMessage = this.addMessage.bind(this);
+        this.updateMessage = this.updateMessage.bind(this);
+        this.deleteMessage = this.deleteMessage.bind(this);
+        this.addLifeline = this.addLifeline.bind(this);
+        this.updateLifeline = this.updateLifeline.bind(this);
+        this.deleteLifeline = this.deleteLifeline.bind(this);
+
+        this.selectMessage = this.selectMessage.bind(this);
+        this.selectLifeline = this.selectLifeline.bind(this);
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select message by ID.
+     * @param id message ID.
+     */
+    selectMessage(id) {
+        // TODO: scroll into view.
+
+        this.setState({ activeMessageId: id });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Select lifeline by ID.
+     * @param id lifeline ID.
+     */
+    selectLifeline(id) {
+        // TODO: scroll into view.
+
+        this.setState({ activeLifelineId: id });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show/hide lifelines section.
+     */
+    onToggle() {
+        const lifelinesExpanded = !this.state.lifelinesExpanded;
+        const messagesExpanded = !lifelinesExpanded;
+        this.setState({ lifelinesExpanded, messagesExpanded });
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle mouse event.
+     * @param id lifeline identifier.
+     */
+    onMouseEnterLifeline(id) {
+        this.application.selectLifeline(id);
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle mouse event.
+     */
+    onMouseLeaveLifeline() {
+        this.application.selectLifeline();
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle mouse event.
+     * @param id message identifier.
+     */
+    onMouseEnterMessage(id) {
+        this.application.selectMessage(id);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
+    /**
+     * Handle mouse event.
+     */
+    onMouseLeaveMessage() {
+        // Only on next selection.
+        // this.application.selectMessage();
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Add new message.
+     */
+    addMessage() {
+        if (this.application.getModel().unwrap().diagram.lifelines.length < 2) {
+            this.application.showErrorDialog(
+                'You need at least two lifelines.'
+            );
+            return;
+        }
 
-    Logger.noop();
-
-    this.application = Common.assertNotNull(props.application);
-
-    this.state = {
-      lifelinesExpanded: false,
-      messagesExpanded: true,
-      activeLifelineId: undefined,
-      activeMessageId: undefined,
-    };
-
-    // Bind this.
-
-    this.onToggle = this.onToggle.bind(this);
-    this.onMouseEnterLifeline = this.onMouseEnterLifeline.bind(this);
-    this.onMouseLeaveLifeline = this.onMouseLeaveLifeline.bind(this);
-    this.onMouseEnterMessage = this.onMouseEnterMessage.bind(this);
-    this.onMouseLeaveMessage = this.onMouseLeaveMessage.bind(this);
-
-    this.addMessage = this.addMessage.bind(this);
-    this.updateMessage = this.updateMessage.bind(this);
-    this.deleteMessage = this.deleteMessage.bind(this);
-    this.addLifeline = this.addLifeline.bind(this);
-    this.updateLifeline = this.updateLifeline.bind(this);
-    this.deleteLifeline = this.deleteLifeline.bind(this);
-
-    this.selectMessage = this.selectMessage.bind(this);
-    this.selectLifeline = this.selectLifeline.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Select message by ID.
-   * @param id message ID.
-   */
-  selectMessage(id) {
-
-    // TODO: scroll into view.
-
-    this.setState({ activeMessageId: id });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Select lifeline by ID.
-   * @param id lifeline ID.
-   */
-  selectLifeline(id) {
-
-    // TODO: scroll into view.
-
-    this.setState({ activeLifelineId: id });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show/hide lifelines section.
-   */
-  onToggle() {
-    const lifelinesExpanded = !this.state.lifelinesExpanded;
-    const messagesExpanded = !lifelinesExpanded;
-    this.setState({ lifelinesExpanded, messagesExpanded });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   * @param id lifeline identifier.
-   */
-  onMouseEnterLifeline(id) {
-    this.application.selectLifeline(id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   */
-  onMouseLeaveLifeline() {
-    this.application.selectLifeline();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   * @param id message identifier.
-   */
-  onMouseEnterMessage(id) {
-    this.application.selectMessage(id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   */
-  onMouseLeaveMessage() {
-    // Only on next selection.
-    // this.application.selectMessage();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Add new message.
-   */
-  addMessage() {
-
-    if (this.application.getModel().unwrap().diagram.lifelines.length < 2) {
-      this.application.showErrorDialog('You need at least two lifelines.');
-      return;
+        this.application.getModel().addMessage();
+        this.forceUpdate();
+        this.application.renderDiagram();
     }
 
-    this.application.getModel().addMessage();
-    this.forceUpdate();
-    this.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Apply property changes to the message identified by props.id.
-   * @param props properties to be updated (excluding 'id').
-   */
-  updateMessage(props) {
-    Common.assertPlainObject(props);
-    const model = this.application.getModel();
-    const message = model.getMessageById(props.id);
-    if (message) {
-      for (const k of Object.keys(props)) {
-        if (k !== 'id') {
-          message[k] = props[k];
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Apply property changes to the message identified by props.id.
+     * @param props properties to be updated (excluding 'id').
+     */
+    updateMessage(props) {
+        Common.assertPlainObject(props);
+        const model = this.application.getModel();
+        const message = model.getMessageById(props.id);
+        if (message) {
+            for (const k of Object.keys(props)) {
+                if (k !== 'id') {
+                    message[k] = props[k];
+                }
+            }
         }
-      }
+        this.forceUpdate();
+        this.application.renderDiagram();
     }
-    this.forceUpdate();
-    this.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Delete message after confirmation.
-   * @param id ID of message to be deleted.
-   */
-  deleteMessage(id) {
-
-    const self = this;
-    const model = this.application.getModel();
-
-    const confirmComplete = function f() {
-      model.deleteMessageById(id);
-      self.render();
-      self.application.renderDiagram();
-    };
-
-    this.application.showConfirmDialog('Delete this message?',
-      confirmComplete);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Add new lifeline.
-   */
-  addLifeline() {
-    this.application.getModel().addLifeline();
-    this.forceUpdate();
-    this.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Apply property changes to the lifeline identified by props.id.
-   * @param props properties to be updated (excluding 'id').
-   */
-  updateLifeline(props) {
-    Common.assertPlainObject(props);
-    const model = this.application.getModel();
-    const lifeline = model.getLifelineById(props.id);
-    if (lifeline) {
-      for (const k of Object.keys(props)) {
-        if (k !== 'id') {
-          lifeline[k] = props[k];
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Delete message after confirmation.
+     * @param id ID of message to be deleted.
+     */
+    deleteMessage(id) {
+        const self = this;
+        const model = this.application.getModel();
+
+        const confirmComplete = function f() {
+            model.deleteMessageById(id);
+            self.render();
+            self.application.renderDiagram();
+        };
+
+        this.application.showConfirmDialog(
+            'Delete this message?',
+            confirmComplete
+        );
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Add new lifeline.
+     */
+    addLifeline() {
+        this.application.getModel().addLifeline();
+        this.forceUpdate();
+        this.application.renderDiagram();
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Apply property changes to the lifeline identified by props.id.
+     * @param props properties to be updated (excluding 'id').
+     */
+    updateLifeline(props) {
+        Common.assertPlainObject(props);
+        const model = this.application.getModel();
+        const lifeline = model.getLifelineById(props.id);
+        if (lifeline) {
+            for (const k of Object.keys(props)) {
+                if (k !== 'id') {
+                    lifeline[k] = props[k];
+                }
+            }
         }
-      }
+        this.forceUpdate();
+        this.application.renderDiagram();
     }
-    this.forceUpdate();
-    this.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Delete lifeline after confirmation.
-   * @param id candidate for deletion.
-   */
-  deleteLifeline(id) {
-
-    const self = this;
-    const model = this.application.getModel();
-
-    const confirmComplete = function f() {
-      model.deleteLifelineById(id);
-      self.forceUpdate();
-      self.application.renderDiagram();
-    };
-    this.application.showConfirmDialog('Delete this lifeline and all its steps?',
-      confirmComplete);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render designer.
-   */
-  render() {
-
-    const application = this.props.application;
-    const model = application.getModel();
-    const diagram = model.unwrap().diagram;
-    const metadata = diagram.metadata;
-
-    const lifelinesIcon = this.state.lifelinesExpanded ? iconExpanded : iconCollapsed;
-    const lifelinesClass = this.state.lifelinesExpanded ? '' : 'asdcs-hidden';
-    const messagesIcon = this.state.messagesExpanded ? iconExpanded : iconCollapsed;
-    const messagesClass = this.state.messagesExpanded ? '' : 'asdcs-hidden';
-
-    return (
-
-      <div className="asdcs-editor-designer">
-        <div className="asdcs-designer-accordion">
-
-          <div className="asdcs-designer-metadata-container">
-            <Metadata metadata={metadata} />
-          </div>
-
-          <h3 onClick={this.onToggle}>Lifelines
-            <div className="asdcs-designer-icon" onClick={this.onToggle}>
-              <Icon glyph={lifelinesIcon} />
-            </div>
-          </h3>
-
-          <div className={`asdcs-designer-lifelines-container ${lifelinesClass}`}>
-            <Lifelines
-              application={this.application}
-              designer={this}
-              activeLifelineId={this.state.activeLifelineId}
-            />
-          </div>
-
-          <h3 onClick={this.onToggle}>Steps
-            <div className="asdcs-designer-icon" onClick={this.onToggle}>
-              <Icon glyph={messagesIcon} />
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Delete lifeline after confirmation.
+     * @param id candidate for deletion.
+     */
+    deleteLifeline(id) {
+        const self = this;
+        const model = this.application.getModel();
+
+        const confirmComplete = function f() {
+            model.deleteLifelineById(id);
+            self.forceUpdate();
+            self.application.renderDiagram();
+        };
+        this.application.showConfirmDialog(
+            'Delete this lifeline and all its steps?',
+            confirmComplete
+        );
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render designer.
+     */
+    render() {
+        const application = this.props.application;
+        const model = application.getModel();
+        const diagram = model.unwrap().diagram;
+        const metadata = diagram.metadata;
+
+        const lifelinesIcon = this.state.lifelinesExpanded
+            ? iconExpanded
+            : iconCollapsed;
+        const lifelinesClass = this.state.lifelinesExpanded
+            ? ''
+            : 'asdcs-hidden';
+        const messagesIcon = this.state.messagesExpanded
+            ? iconExpanded
+            : iconCollapsed;
+        const messagesClass = this.state.messagesExpanded ? '' : 'asdcs-hidden';
+
+        return (
+            <div className="asdcs-editor-designer">
+                <div className="asdcs-designer-accordion">
+                    <div className="asdcs-designer-metadata-container">
+                        <Metadata metadata={metadata} />
+                    </div>
+
+                    <h3 onClick={this.onToggle}>
+                        Lifelines
+                        <div
+                            className="asdcs-designer-icon"
+                            onClick={this.onToggle}>
+                            <Icon glyph={lifelinesIcon} />
+                        </div>
+                    </h3>
+
+                    <div
+                        className={`asdcs-designer-lifelines-container ${lifelinesClass}`}>
+                        <Lifelines
+                            application={this.application}
+                            designer={this}
+                            activeLifelineId={this.state.activeLifelineId}
+                        />
+                    </div>
+
+                    <h3 onClick={this.onToggle}>
+                        Steps
+                        <div
+                            className="asdcs-designer-icon"
+                            onClick={this.onToggle}>
+                            <Icon glyph={messagesIcon} />
+                        </div>
+                    </h3>
+
+                    <div
+                        className={`asdcs-designer-steps-container ${messagesClass}`}>
+                        <Messages
+                            application={this.application}
+                            designer={this}
+                            activeMessageId={this.state.activeMessageId}
+                        />
+                    </div>
+                </div>
+
+                <Actions
+                    application={this.props.application}
+                    model={model}
+                    ref={r => {
+                        this.actions = r;
+                    }}
+                />
             </div>
-          </h3>
-
-          <div className={`asdcs-designer-steps-container ${messagesClass}`} >
-            <Messages
-              application={this.application}
-              designer={this}
-              activeMessageId={this.state.activeMessageId}
-            />
-          </div>
-
-        </div>
-
-        <Actions
-          application={this.props.application}
-          model={model}
-          ref={(r) => { this.actions = r; }}
-        />
-
-      </div>
-    );
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Scroll accordion pane to make
-   * @param $element focused element.
-   * @private
-   */
-  static _scrollIntoView($element) {
-    const $pane = $element.closest('.ui-accordion-content');
-    const paneScrollTop = $pane.scrollTop();
-    const paneHeight = $pane.height();
-    const paneBottom = paneScrollTop + paneHeight;
-    const elementTop = $element[0].offsetTop - $pane[0].offsetTop;
-    const elementHeight = $element.height();
-    const elementBottom = elementTop + elementHeight;
-    if (elementBottom > paneBottom) {
-      $pane.scrollTop(elementTop);
-    } else if (elementTop < paneScrollTop) {
-      $pane.scrollTop(elementTop);
+        );
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Scroll accordion pane to make
+     * @param $element focused element.
+     * @private
+     */
+    static _scrollIntoView($element) {
+        const $pane = $element.closest('.ui-accordion-content');
+        const paneScrollTop = $pane.scrollTop();
+        const paneHeight = $pane.height();
+        const paneBottom = paneScrollTop + paneHeight;
+        const elementTop = $element[0].offsetTop - $pane[0].offsetTop;
+        const elementHeight = $element.height();
+        const elementBottom = elementTop + elementHeight;
+        if (elementBottom > paneBottom) {
+            $pane.scrollTop(elementTop);
+        } else if (elementTop < paneScrollTop) {
+            $pane.scrollTop(elementTop);
+        }
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show actions menu.
-   * @param id selected message ID.
-   * @param position page coordinates.
-   */
-  showActions(id, position) {
-    if (this.actions) {
-      this.actions.show(id, position);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show actions menu.
+     * @param id selected message ID.
+     * @param position page coordinates.
+     */
+    showActions(id, position) {
+        if (this.actions) {
+            this.actions.show(id, position);
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show notes popup.
+     * @param id selected message identifier.
+     */
+    showNotes(id) {
+        const model = this.application.getModel();
+        const options = this.application.getOptions();
+        const message = model.getMessageById(id);
+        const notes =
+            message.notes && message.notes.length > 0 ? message.notes[0] : '';
+        const editComplete = function f(p) {
+            message.notes = [];
+            if (p && p.text) {
+                const sanitized = Common.sanitizeText(p.text, options, 'notes');
+                message.notes.push(sanitized);
+            }
+        };
+        this.application.showEditDialog('Notes:', notes, editComplete);
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show notes popup.
-   * @param id selected message identifier.
-   */
-  showNotes(id) {
-    const model = this.application.getModel();
-    const options = this.application.getOptions();
-    const message = model.getMessageById(id);
-    const notes = (message.notes && (message.notes.length > 0)) ? message.notes[0] : '';
-    const editComplete = function f(p) {
-      message.notes = [];
-      if (p && p.text) {
-        const sanitized = Common.sanitizeText(p.text, options, 'notes');
-        message.notes.push(sanitized);
-      }
-    };
-    this.application.showEditDialog('Notes:', notes, editComplete);
-  }
 }
 
 /** Element properties. */
 Designer.propTypes = {
-  application: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired
 };
 
+/* eslint-disable new-cap */
 export default DragDropContext(HTML5Backend)(Designer);
+/* eslint-enable new-cap */
index 5a8343c..a558a14 100644 (file)
@@ -36,439 +36,499 @@ import iconFragmentStop from '../../../../../../../../../../res/ecomp/asdc/seque
  * Action menu view.
  */
 class Actions extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
+        Logger.noop();
 
-    Logger.noop();
+        this.state = {
+            id: undefined,
+            visible: false
+        };
 
-    this.state = {
-      id: undefined,
-      visible: false,
-    };
+        // Bindings.
 
-    // Bindings.
+        this.show = this.show.bind(this);
 
-    this.show = this.show.bind(this);
+        this.onClickOccurrenceToggle = this.onClickOccurrenceToggle.bind(this);
+        this.onClickOccurrenceFrom = this.onClickOccurrenceFrom.bind(this);
+        this.onClickOccurrenceTo = this.onClickOccurrenceTo.bind(this);
 
-    this.onClickOccurrenceToggle = this.onClickOccurrenceToggle.bind(this);
-    this.onClickOccurrenceFrom = this.onClickOccurrenceFrom.bind(this);
-    this.onClickOccurrenceTo = this.onClickOccurrenceTo.bind(this);
+        this.onClickFragmentToggle = this.onClickFragmentToggle.bind(this);
+        this.onChangeFragmentGuard = this.onChangeFragmentGuard.bind(this);
+        this.onChangeFragmentOperator = this.onChangeFragmentOperator.bind(
+            this
+        );
 
-    this.onClickFragmentToggle = this.onClickFragmentToggle.bind(this);
-    this.onChangeFragmentGuard = this.onChangeFragmentGuard.bind(this);
-    this.onChangeFragmentOperator = this.onChangeFragmentOperator.bind(this);
-
-    this.onMouseOut = this.onMouseOut.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Show for message.
-   * @param id message ID.
-   * @param position xy coordinates.
-   */
-  show(id, position) {
-    const message = this.props.model.getMessageById(id);
-
-    let occurrencesToggle = false;
-    let fragmentToggle = false;
-    if (message) {
-
-      message.occurrences = message.occurrences || { start: [], stop: [] };
-      message.occurrences.start = message.occurrences.start || [];
-      message.occurrences.stop = message.occurrences.stop || [];
-      message.fragment = message.fragment || {};
-      message.fragment.start = message.fragment.start || false;
-      message.fragment.stop = message.fragment.stop || false;
-      message.fragment.guard = message.fragment.guard || '';
-      message.fragment.operator = message.fragment.operator || '';
-
-      const mo = message.occurrences;
-      occurrencesToggle = (mo.start.length > 0 || mo.stop.length > 0);
-
-      const mf = message.fragment;
-      fragmentToggle = (mf.start || mf.stop);
+        this.onMouseOut = this.onMouseOut.bind(this);
     }
 
-    this.setState({
-      id,
-      message,
-      occurrencesToggle,
-      fragmentToggle,
-      visible: true,
-      x: position.x,
-      y: position.y,
-    });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Toggle occurrence state.
-   */
-  onClickOccurrenceToggle() {
-    const message = this.state.message;
-    if (message) {
-      const oFromState = Actions.getOccurrenceState(message.occurrences, message.from);
-      const oToState = Actions.getOccurrenceState(message.occurrences, message.to);
-      const oExpanded = oFromState > 0 || oToState > 0;
-      if (oExpanded) {
-        this.setState({ occurrencesExpanded: true });
-      } else {
-        const occurrencesExpanded = !this.state.occurrencesExpanded;
-        this.setState({ occurrencesExpanded });
-      }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Show for message.
+     * @param id message ID.
+     * @param position xy coordinates.
+     */
+    show(id, position) {
+        const message = this.props.model.getMessageById(id);
+
+        let occurrencesToggle = false;
+        let fragmentToggle = false;
+        if (message) {
+            message.occurrences = message.occurrences || {
+                start: [],
+                stop: []
+            };
+            message.occurrences.start = message.occurrences.start || [];
+            message.occurrences.stop = message.occurrences.stop || [];
+            message.fragment = message.fragment || {};
+            message.fragment.start = message.fragment.start || false;
+            message.fragment.stop = message.fragment.stop || false;
+            message.fragment.guard = message.fragment.guard || '';
+            message.fragment.operator = message.fragment.operator || '';
+
+            const mo = message.occurrences;
+            occurrencesToggle = mo.start.length > 0 || mo.stop.length > 0;
+
+            const mf = message.fragment;
+            fragmentToggle = mf.start || mf.stop;
+        }
+
+        this.setState({
+            id,
+            message,
+            occurrencesToggle,
+            fragmentToggle,
+            visible: true,
+            x: position.x,
+            y: position.y
+        });
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Handle menu click.
-   */
-  onClickOccurrenceFrom() {
-    const message = this.state.message;
-    if (message) {
-      Actions._toggleOccurrence(message.occurrences, message.from);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Toggle occurrence state.
+     */
+    onClickOccurrenceToggle() {
+        const message = this.state.message;
+        if (message) {
+            const oFromState = Actions.getOccurrenceState(
+                message.occurrences,
+                message.from
+            );
+            const oToState = Actions.getOccurrenceState(
+                message.occurrences,
+                message.to
+            );
+            const oExpanded = oFromState > 0 || oToState > 0;
+            if (oExpanded) {
+                this.setState({ occurrencesExpanded: true });
+            } else {
+                const occurrencesExpanded = !this.state.occurrencesExpanded;
+                this.setState({ occurrencesExpanded });
+            }
+        }
     }
-    this.setState({ message });
-    this.props.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle menu click.
-   */
-  onClickOccurrenceTo() {
-    const message = this.state.message;
-    if (message) {
-      Actions._toggleOccurrence(message.occurrences, message.to);
-    }
-    this.setState({ message });
-    this.props.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Toggle fragment.
-   */
-  onClickFragmentToggle() {
-    const message = this.state.message;
-    if (message) {
-      Actions._toggleFragment(message.fragment);
-    }
-    this.setState({ message });
-    this.props.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle menu click.
-   * @param event update event.
-   */
-  onChangeFragmentGuard(event) {
-    const message = this.state.message;
-    if (message) {
-      const options = this.props.application.getOptions();
-      message.fragment.guard = Common.sanitizeText(event.target.value, options, 'guard');
-    }
-    this.setState({ message });
-    this.props.application.renderDiagram();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle menu click.
-   * @param value updated value.
-   */
-  onChangeFragmentOperator(value) {
-    const message = this.state.message;
-    if (message) {
-      message.fragment.operator = value.value;
-    }
-    this.setState({ message });
-    this.props.application.renderDiagram();
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     */
+    onClickOccurrenceFrom() {
+        const message = this.state.message;
+        if (message) {
+            Actions._toggleOccurrence(message.occurrences, message.from);
+        }
+        this.setState({ message });
+        this.props.application.renderDiagram();
+    }
 
-  /**
-   * Handle mouse movement.
-   */
-  onMouseOut() {
-    this.setState({ id: -1, visible: false, x: 0, y: 0 });
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     */
+    onClickOccurrenceTo() {
+        const message = this.state.message;
+        if (message) {
+            Actions._toggleOccurrence(message.occurrences, message.to);
+        }
+        this.setState({ message });
+        this.props.application.renderDiagram();
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Toggle fragment.
+     */
+    onClickFragmentToggle() {
+        const message = this.state.message;
+        if (message) {
+            Actions._toggleFragment(message.fragment);
+        }
+        this.setState({ message });
+        this.props.application.renderDiagram();
+    }
 
-  /**
-   * Render view.
-   * @returns {XML}
-   */
-  render() {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     * @param event update event.
+     */
+    onChangeFragmentGuard(event) {
+        const message = this.state.message;
+        if (message) {
+            const options = this.props.application.getOptions();
+            message.fragment.guard = Common.sanitizeText(
+                event.target.value,
+                options,
+                'guard'
+            );
+        }
+        this.setState({ message });
+        this.props.application.renderDiagram();
+    }
 
-    const actionsStyles = { };
-    const message = this.state.message;
-    if (!message || !this.state.visible) {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     * @param value updated value.
+     */
+    onChangeFragmentOperator(value) {
+        const message = this.state.message;
+        if (message) {
+            message.fragment.operator = value.value;
+        }
+        this.setState({ message });
+        this.props.application.renderDiagram();
+    }
 
-      // Invisible.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-      return (<div className="asdcs-actions" ></div>);
+    /**
+     * Handle mouse movement.
+     */
+    onMouseOut() {
+        this.setState({ id: -1, visible: false, x: 0, y: 0 });
     }
 
-    // Position and display.
-
-    actionsStyles.display = 'block';
-    actionsStyles.left = this.state.x - 10;
-    actionsStyles.top = this.state.y - 10;
-
-    const oFromState = Actions.getOccurrenceState(message.occurrences, message.from);
-    const oToState = Actions.getOccurrenceState(message.occurrences, message.to);
-    const fState = Actions.getFragmentState(message.fragment);
-
-    const oExpanded = this.state.occurrencesExpanded || (oFromState > 0) || (oToState > 0);
-    const oAuxClassName = oExpanded ? '' : 'asdcs-hidden';
-
-    const fExpanded = fState !== 0;
-    const fAuxClassName = fExpanded ? '' : 'asdcs-hidden';
-
-    const fragmentOperatorOptions = [{
-      value: 'alt',
-      label: 'Alternate',
-    }, {
-      value: 'opt',
-      label: 'Optional',
-    }, {
-      value: 'loop',
-      label: 'Loop',
-    }];
-
-    const operator = message.fragment.operator || 'alt';
-
-    return (
-      <div
-        className="asdcs-actions"
-        style={actionsStyles}
-        onMouseLeave={this.onMouseOut}
-      >
-        <div className="asdcs-actions-header">
-          <div className="asdcs-actions-icon">
-            <Icon glyph={iconSettings} />
-          </div>
-        </div>
-
-        <div className="asdcs-actions-options">
-
-          <div className="asdcs-actions-optiongroup asdcs-actions-optiongroup-occurrence">
-            <div
-              className="asdcs-actions-option asdcs-actions-option-occurrence-toggle"
-              onClick={this.onClickOccurrenceToggle}
-            >
-              <span className="asdcs-label">Occurrence</span>
-              <div className="asdcs-actions-state">
-                <Icon glyph={iconCollapsed} className={oExpanded ? 'asdcs-hidden' : ''} />
-                <Icon glyph={iconExpanded} className={oExpanded ? '' : 'asdcs-hidden'} />
-              </div>
-            </div>
-          </div>
-
-          <div
-            className={`asdcs-actions-option asdcs-actions-option-occurrence-from ${oAuxClassName}`}
-            onClick={this.onClickOccurrenceFrom}
-          >
-            <span className="asdcs-label">From</span>
-            <div className="asdcs-actions-state">
-              <span className="asdcs-annotation"></span>
-              <Icon glyph={iconOccurrenceDefault} className={oFromState === 0 ? '' : 'asdcs-hidden'} />
-              <Icon glyph={iconOccurrenceStart} className={oFromState === 1 ? '' : 'asdcs-hidden'} />
-              <Icon glyph={iconOccurrenceStop} className={oFromState === 2 ? '' : 'asdcs-hidden'} />
-            </div>
-          </div>
-
-          <div
-            className={`asdcs-actions-option asdcs-actions-option-occurrence-to ${oAuxClassName}`}
-            onClick={this.onClickOccurrenceTo}
-          >
-            <span className="asdcs-label">To</span>
-            <div className="asdcs-actions-state">
-              <span className="asdcs-annotation"></span>
-              <Icon glyph={iconOccurrenceDefault} className={oToState === 0 ? '' : 'asdcs-hidden'} />
-              <Icon glyph={iconOccurrenceStart} className={oToState === 1 ? '' : 'asdcs-hidden'} />
-              <Icon glyph={iconOccurrenceStop} className={oToState === 2 ? '' : 'asdcs-hidden'} />
-            </div>
-          </div>
-
-          <div className="asdcs-actions-optiongroup asdcs-actions-optiongroup-fragment">
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render view.
+     * @returns {XML}
+     */
+    render() {
+        const actionsStyles = {};
+        const message = this.state.message;
+        if (!message || !this.state.visible) {
+            // Invisible.
+
+            return <div className="asdcs-actions" />;
+        }
+
+        // Position and display.
+
+        actionsStyles.display = 'block';
+        actionsStyles.left = this.state.x - 10;
+        actionsStyles.top = this.state.y - 10;
+
+        const oFromState = Actions.getOccurrenceState(
+            message.occurrences,
+            message.from
+        );
+        const oToState = Actions.getOccurrenceState(
+            message.occurrences,
+            message.to
+        );
+        const fState = Actions.getFragmentState(message.fragment);
+
+        const oExpanded =
+            this.state.occurrencesExpanded || oFromState > 0 || oToState > 0;
+        const oAuxClassName = oExpanded ? '' : 'asdcs-hidden';
+
+        const fExpanded = fState !== 0;
+        const fAuxClassName = fExpanded ? '' : 'asdcs-hidden';
+
+        const fragmentOperatorOptions = [
+            {
+                value: 'alt',
+                label: 'Alternate'
+            },
+            {
+                value: 'opt',
+                label: 'Optional'
+            },
+            {
+                value: 'loop',
+                label: 'Loop'
+            }
+        ];
+
+        const operator = message.fragment.operator || 'alt';
+
+        return (
             <div
-              className="asdcs-actions-option asdcs-actions-fragment-toggle"
-              onClick={this.onClickFragmentToggle}
-            >
-              <span className="asdcs-label">Fragment</span>
-              <div className="asdcs-actions-state">
-                <span className="asdcs-annotation"></span>
-                <Icon glyph={iconFragmentDefault} className={fState === 0 ? '' : 'asdcs-hidden'} />
-                <Icon glyph={iconFragmentStart} className={fState === 1 ? '' : 'asdcs-hidden'} />
-                <Icon glyph={iconFragmentStop} className={fState === 2 ? '' : 'asdcs-hidden'} />
-              </div>
+                className="asdcs-actions"
+                style={actionsStyles}
+                onMouseLeave={this.onMouseOut}>
+                <div className="asdcs-actions-header">
+                    <div className="asdcs-actions-icon">
+                        <Icon glyph={iconSettings} />
+                    </div>
+                </div>
+
+                <div className="asdcs-actions-options">
+                    <div className="asdcs-actions-optiongroup asdcs-actions-optiongroup-occurrence">
+                        <div
+                            className="asdcs-actions-option asdcs-actions-option-occurrence-toggle"
+                            onClick={this.onClickOccurrenceToggle}>
+                            <span className="asdcs-label">Occurrence</span>
+                            <div className="asdcs-actions-state">
+                                <Icon
+                                    glyph={iconCollapsed}
+                                    className={oExpanded ? 'asdcs-hidden' : ''}
+                                />
+                                <Icon
+                                    glyph={iconExpanded}
+                                    className={oExpanded ? '' : 'asdcs-hidden'}
+                                />
+                            </div>
+                        </div>
+                    </div>
+
+                    <div
+                        className={`asdcs-actions-option asdcs-actions-option-occurrence-from ${oAuxClassName}`}
+                        onClick={this.onClickOccurrenceFrom}>
+                        <span className="asdcs-label">From</span>
+                        <div className="asdcs-actions-state">
+                            <span className="asdcs-annotation" />
+                            <Icon
+                                glyph={iconOccurrenceDefault}
+                                className={
+                                    oFromState === 0 ? '' : 'asdcs-hidden'
+                                }
+                            />
+                            <Icon
+                                glyph={iconOccurrenceStart}
+                                className={
+                                    oFromState === 1 ? '' : 'asdcs-hidden'
+                                }
+                            />
+                            <Icon
+                                glyph={iconOccurrenceStop}
+                                className={
+                                    oFromState === 2 ? '' : 'asdcs-hidden'
+                                }
+                            />
+                        </div>
+                    </div>
+
+                    <div
+                        className={`asdcs-actions-option asdcs-actions-option-occurrence-to ${oAuxClassName}`}
+                        onClick={this.onClickOccurrenceTo}>
+                        <span className="asdcs-label">To</span>
+                        <div className="asdcs-actions-state">
+                            <span className="asdcs-annotation" />
+                            <Icon
+                                glyph={iconOccurrenceDefault}
+                                className={oToState === 0 ? '' : 'asdcs-hidden'}
+                            />
+                            <Icon
+                                glyph={iconOccurrenceStart}
+                                className={oToState === 1 ? '' : 'asdcs-hidden'}
+                            />
+                            <Icon
+                                glyph={iconOccurrenceStop}
+                                className={oToState === 2 ? '' : 'asdcs-hidden'}
+                            />
+                        </div>
+                    </div>
+
+                    <div className="asdcs-actions-optiongroup asdcs-actions-optiongroup-fragment">
+                        <div
+                            className="asdcs-actions-option asdcs-actions-fragment-toggle"
+                            onClick={this.onClickFragmentToggle}>
+                            <span className="asdcs-label">Fragment</span>
+                            <div className="asdcs-actions-state">
+                                <span className="asdcs-annotation" />
+                                <Icon
+                                    glyph={iconFragmentDefault}
+                                    className={
+                                        fState === 0 ? '' : 'asdcs-hidden'
+                                    }
+                                />
+                                <Icon
+                                    glyph={iconFragmentStart}
+                                    className={
+                                        fState === 1 ? '' : 'asdcs-hidden'
+                                    }
+                                />
+                                <Icon
+                                    glyph={iconFragmentStop}
+                                    className={
+                                        fState === 2 ? '' : 'asdcs-hidden'
+                                    }
+                                />
+                            </div>
+                        </div>
+                    </div>
+
+                    <div
+                        className={`asdcs-actions-option asdcs-actions-fragment-operator ${fAuxClassName}`}>
+                        <div className="asdcs-label">Operator</div>
+                        <div className="asdcs-value">
+                            <Select
+                                className="asdcs-editable-select"
+                                openOnFocus
+                                clearable={false}
+                                searchable={false}
+                                value={operator}
+                                onChange={this.onChangeFragmentOperator}
+                                options={fragmentOperatorOptions}
+                            />
+                        </div>
+                    </div>
+
+                    <div
+                        className={`asdcs-actions-option asdcs-actions-fragment-guard ${fAuxClassName}`}>
+                        <div className="asdcs-label">Guard</div>
+                        <div className="asdcs-value">
+                            <input
+                                className="asdcs-editable"
+                                type="text"
+                                size="20"
+                                maxLength="80"
+                                value={message.fragment.guard}
+                                placeholder="Condition"
+                                onChange={this.onChangeFragmentGuard}
+                            />
+                        </div>
+                    </div>
+                </div>
+
+                <div className="asdcs-actions-footer" />
             </div>
-          </div>
-
-          <div className={`asdcs-actions-option asdcs-actions-fragment-operator ${fAuxClassName}`}>
-            <div className="asdcs-label">Operator</div>
-            <div className="asdcs-value">
-              <Select
-                className="asdcs-editable-select"
-                openOnFocus
-                clearable={false}
-                searchable={false}
-                value={operator}
-                onChange={this.onChangeFragmentOperator}
-                options={fragmentOperatorOptions}
-              />
-            </div>
-          </div>
-
-          <div className={`asdcs-actions-option asdcs-actions-fragment-guard ${fAuxClassName}`}>
-            <div className="asdcs-label">Guard</div>
-            <div className="asdcs-value">
-              <input
-                className="asdcs-editable"
-                type="text"
-                size="20"
-                maxLength="80"
-                value={message.fragment.guard}
-                placeholder="Condition"
-                onChange={this.onChangeFragmentGuard}
-              />
-            </div>
-          </div>
-
-        </div>
-
-        <div className="asdcs-actions-footer"></div>
-
-      </div>
-
-    );
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Toggle through three occurrence states on click.
-   * @param occurrence occurrences state, updated as side-effect.
-   * @param lifelineId message end that's being toggled.
-   * @private
-   */
-  static _toggleOccurrence(occurrence, lifelineId) {
-    const o = occurrence;
-
-    const rm = function rm(array, value) {
-      const index = array.indexOf(value);
-      if (index !== -1) {
-        array.splice(index, 1);
-      }
-    };
-
-    const add = function add(array, value) {
-      if (array.indexOf(value) === -1) {
-        array.push(value);
-      }
-    };
-
-    if (o.start && o.start.indexOf(lifelineId) !== -1) {
-      // Start -> stop.
-      rm(o.start, lifelineId);
-      add(o.stop, lifelineId);
-    } else if (o.stop && o.stop.indexOf(lifelineId) !== -1) {
-      // Stop -> default.
-      rm(o.start, lifelineId);
-      rm(o.stop, lifelineId);
-    } else {
-      // Default -> start.
-      add(o.start, lifelineId);
-      rm(o.stop, lifelineId);
+        );
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Toggle fragment setting on click.
-   * @param fragment
-   * @private
-   **/
-  static _toggleFragment(fragment) {
-    const f = fragment;
-    if (f.start === true) {
-      f.start = false;
-      f.stop = true;
-    } else if (f.stop === true) {
-      f.stop = false;
-      f.start = false;
-    } else {
-      f.start = true;
-      f.stop = false;
-    }
-    f.guard = '';
-    f.operator = '';
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get ternary occurrences state.
-   * @param o occurrences.
-   * @param lifelineId from/to lifeline ID.
-   * @returns {number}
-   * @private
-   */
-  static getOccurrenceState(o, lifelineId) {
-    if (o.start.indexOf(lifelineId) !== -1) {
-      return 1;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Toggle through three occurrence states on click.
+     * @param occurrence occurrences state, updated as side-effect.
+     * @param lifelineId message end that's being toggled.
+     * @private
+     */
+    static _toggleOccurrence(occurrence, lifelineId) {
+        const o = occurrence;
+
+        const rm = function rm(array, value) {
+            const index = array.indexOf(value);
+            if (index !== -1) {
+                array.splice(index, 1);
+            }
+        };
+
+        const add = function add(array, value) {
+            if (array.indexOf(value) === -1) {
+                array.push(value);
+            }
+        };
+
+        if (o.start && o.start.indexOf(lifelineId) !== -1) {
+            // Start -> stop.
+            rm(o.start, lifelineId);
+            add(o.stop, lifelineId);
+        } else if (o.stop && o.stop.indexOf(lifelineId) !== -1) {
+            // Stop -> default.
+            rm(o.start, lifelineId);
+            rm(o.stop, lifelineId);
+        } else {
+            // Default -> start.
+            add(o.start, lifelineId);
+            rm(o.stop, lifelineId);
+        }
     }
-    if (o.stop.indexOf(lifelineId) !== -1) {
-      return 2;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Toggle fragment setting on click.
+     * @param fragment
+     * @private
+     **/
+    static _toggleFragment(fragment) {
+        const f = fragment;
+        if (f.start === true) {
+            f.start = false;
+            f.stop = true;
+        } else if (f.stop === true) {
+            f.stop = false;
+            f.start = false;
+        } else {
+            f.start = true;
+            f.stop = false;
+        }
+        f.guard = '';
+        f.operator = '';
     }
-    return 0;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get ternary fragment state.
-   * @param f fragment.
-   * @returns {number}
-   * @private
-   */
-  static getFragmentState(f) {
-    if (f.start) {
-      return 1;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get ternary occurrences state.
+     * @param o occurrences.
+     * @param lifelineId from/to lifeline ID.
+     * @returns {number}
+     * @private
+     */
+    static getOccurrenceState(o, lifelineId) {
+        if (o.start.indexOf(lifelineId) !== -1) {
+            return 1;
+        }
+        if (o.stop.indexOf(lifelineId) !== -1) {
+            return 2;
+        }
+        return 0;
     }
-    if (f.stop) {
-      return 2;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get ternary fragment state.
+     * @param f fragment.
+     * @returns {number}
+     * @private
+     */
+    static getFragmentState(f) {
+        if (f.start) {
+            return 1;
+        }
+        if (f.stop) {
+            return 2;
+        }
+        return 0;
     }
-    return 0;
-  }
 }
 
 /** Element properties. */
 Actions.propTypes = {
-  application: PropTypes.object.isRequired,
-  model: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired,
+    model: PropTypes.object.isRequired
 };
 
 export default Actions;
index 86ee80f..09c8d92 100644 (file)
@@ -28,238 +28,247 @@ import iconDelete from '../../../../../../../../../../res/ecomp/asdc/sequencer/s
  * LHS lifeline row view.
  */
 class Lifeline extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct editor view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        this.state = {
+            active: false,
+            name: props.lifeline.name
+        };
+
+        const metamodel = Common.assertNotNull(this.props.metamodel).unwrap();
+        this.canReorder = metamodel.diagram.lifelines.constraints.reorder;
+        this.canDelete = metamodel.diagram.lifelines.constraints.delete;
+
+        // Bindings.
+
+        this.onChangeName = this.onChangeName.bind(this);
+        this.onBlurName = this.onBlurName.bind(this);
+        this.onClickDelete = this.onClickDelete.bind(this);
+        this.onMouseEnter = this.onMouseEnter.bind(this);
+        this.onMouseLeave = this.onMouseLeave.bind(this);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct editor view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-
-    this.state = {
-      active: false,
-      name: props.lifeline.name,
-    };
-
-    const metamodel = Common.assertNotNull(this.props.metamodel).unwrap();
-    this.canReorder = metamodel.diagram.lifelines.constraints.reorder;
-    this.canDelete = metamodel.diagram.lifelines.constraints.delete;
-
-    // Bindings.
-
-    this.onChangeName = this.onChangeName.bind(this);
-    this.onBlurName = this.onBlurName.bind(this);
-    this.onClickDelete = this.onClickDelete.bind(this);
-    this.onMouseEnter = this.onMouseEnter.bind(this);
-    this.onMouseLeave = this.onMouseLeave.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle name change.
-   * @param event change event.
-   */
-  onChangeName(event) {
-    this.setState({ name: event.target.value });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle name change.
-   * @param event change event.
-   */
-  onBlurName(event) {
-    const options = this.props.application.getOptions();
-    const sanitized = Common.sanitizeText(event.target.value, options, 'lifeline');
-    const props = {
-      id: this.props.lifeline.id,
-      name: sanitized,
-    };
-    this.props.designer.updateLifeline(props);
-    this.setState({ name: sanitized });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Handle lifeline delete.
-   */
-  onClickDelete() {
-    this.props.designer.deleteLifeline(this.props.lifeline.id);
-  }
+    /**
+     * Handle name change.
+     * @param event change event.
+     */
+    onChangeName(event) {
+        this.setState({ name: event.target.value });
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle name change.
+     * @param event change event.
+     */
+    onBlurName(event) {
+        const options = this.props.application.getOptions();
+        const sanitized = Common.sanitizeText(
+            event.target.value,
+            options,
+            'lifeline'
+        );
+        const props = {
+            id: this.props.lifeline.id,
+            name: sanitized
+        };
+        this.props.designer.updateLifeline(props);
+        this.setState({ name: sanitized });
+    }
 
-  /**
-   * Handle mouseover event.
-   */
-  onMouseEnter() {
-    this.setState({ active: true });
-    this.props.designer.onMouseEnterLifeline(this.props.lifeline.id);
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Handle lifeline delete.
+     */
+    onClickDelete() {
+        this.props.designer.deleteLifeline(this.props.lifeline.id);
+    }
 
-  /**
-   * Handle mouseleave event.
-   */
-  onMouseLeave() {
-    this.setState({ active: false });
-    this.props.designer.onMouseLeaveLifeline(this.props.lifeline.id);
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Handle mouseover event.
+     */
+    onMouseEnter() {
+        this.setState({ active: true });
+        this.props.designer.onMouseEnterLifeline(this.props.lifeline.id);
+    }
 
-  /**
-   * Get whether metadata permits reorder.
-   * @returns true if reorderable.
-   */
-  isCanReorder() {
-    return this.canReorder;
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Handle mouseleave event.
+     */
+    onMouseLeave() {
+        this.setState({ active: false });
+        this.props.designer.onMouseLeaveLifeline(this.props.lifeline.id);
+    }
 
-  /**
-   * Get whether metadata permits delete.
-   * @returns true if lifeline can be deleted.
-   */
-  isCanDelete() {
-    return this.canDelete;
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Get whether metadata permits reorder.
+     * @returns true if reorderable.
+     */
+    isCanReorder() {
+        return this.canReorder;
+    }
 
-  /**
-   * React render.
-   * @returns {*}
-   */
-  render() {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    const id = this.props.lifeline.id;
-    const activeClass = (this.props.active === true) ? 'asdcs-active' : '';
-    const { connectDragSource, connectDropTarget } = this.props;
-    return connectDragSource(connectDropTarget(
+    /**
+     * Get whether metadata permits delete.
+     * @returns true if lifeline can be deleted.
+     */
+    isCanDelete() {
+        return this.canDelete;
+    }
 
-      <div
-        className={`asdcs-designer-lifeline ${activeClass}`}
-        data-id={id}
-        onMouseEnter={this.onMouseEnter}
-        onMouseLeave={this.onMouseLeave}
-      >
-        <table className="asdcs-designer-layout asdcs-designer-lifeline-row1">
-          <tbody>
-            <tr>
-              <td>
-                <div className="asdcs-designer-sort asdcs-designer-icon">
-                  <Icon glyph={iconHandle} />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-lifeline-index">{this.props.lifeline.index}.</div>
-              </td>
-              <td>
-                <div className="asdcs-designer-lifeline-name">
-                  <input
-                    type="text"
-                    className="asdcs-editable"
-                    placeholder="Unnamed"
-                    value={this.state.name}
-                    onChange={this.onChangeName}
-                    onBlur={this.onBlurName}
-                  />
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * React render.
+     * @returns {*}
+     */
+    render() {
+        const id = this.props.lifeline.id;
+        const activeClass = this.props.active === true ? 'asdcs-active' : '';
+        const { connectDragSource, connectDropTarget } = this.props;
+        return connectDragSource(
+            connectDropTarget(
+                <div
+                    className={`asdcs-designer-lifeline ${activeClass}`}
+                    data-id={id}
+                    onMouseEnter={this.onMouseEnter}
+                    onMouseLeave={this.onMouseLeave}>
+                    <table className="asdcs-designer-layout asdcs-designer-lifeline-row1">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div className="asdcs-designer-sort asdcs-designer-icon">
+                                        <Icon glyph={iconHandle} />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-lifeline-index">
+                                        {this.props.lifeline.index}.
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-lifeline-name">
+                                        <input
+                                            type="text"
+                                            className="asdcs-editable"
+                                            placeholder="Unnamed"
+                                            value={this.state.name}
+                                            onChange={this.onChangeName}
+                                            onBlur={this.onBlurName}
+                                        />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div
+                                        className="asdcs-designer-delete asdcs-designer-icon"
+                                        onClick={this.onClickDelete}>
+                                        <Icon glyph={iconDelete} />
+                                    </div>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
                 </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-delete asdcs-designer-icon" onClick={this.onClickDelete}>
-                  <Icon glyph={iconDelete} />
-                </div>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    ));
-  }
+            )
+        );
+    }
 }
 
 /**
  * Declare properties.
  */
 Lifeline.propTypes = {
-  application: PropTypes.object.isRequired,
-  designer: PropTypes.object.isRequired,
-  lifeline: PropTypes.object.isRequired,
-  active: PropTypes.bool.isRequired,
-  metamodel: PropTypes.object.isRequired,
-  id: PropTypes.any.isRequired,
-  index: PropTypes.number.isRequired,
-  lifelines: PropTypes.object.isRequired,
-  isDragging: PropTypes.bool.isRequired,
-  connectDragSource: PropTypes.func.isRequired,
-  connectDropTarget: PropTypes.func.isRequired,
+    application: PropTypes.object.isRequired,
+    designer: PropTypes.object.isRequired,
+    lifeline: PropTypes.object.isRequired,
+    active: PropTypes.bool.isRequired,
+    metamodel: PropTypes.object.isRequired,
+    id: PropTypes.any.isRequired,
+    index: PropTypes.number.isRequired,
+    lifelines: PropTypes.object.isRequired,
+    isDragging: PropTypes.bool.isRequired,
+    connectDragSource: PropTypes.func.isRequired,
+    connectDropTarget: PropTypes.func.isRequired
 };
 
 /** DND. */
 const source = {
-  beginDrag(props) {
-    return {
-      id: props.id,
-      index: props.index,
-    };
-  },
+    beginDrag(props) {
+        return {
+            id: props.id,
+            index: props.index
+        };
+    }
 };
 
 /** DND. */
 const sourceCollect = function collection(connect, monitor) {
-  return {
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging(),
-  };
+    return {
+        connectDragSource: connect.dragSource(),
+        isDragging: monitor.isDragging()
+    };
 };
 
 /** DND. */
 const target = {
-  drop(props, monitor, component) {
-    Common.assertNotNull(props);
-    Common.assertNotNull(monitor);
-    const decorated = component.getDecoratedComponentInstance();
-    if (decorated) {
-      const lifelines = decorated.props.lifelines;
-      if (lifelines) {
-        const dragIndex = monitor.getItem().index;
-        const hoverIndex = lifelines.getHoverIndex();
-        lifelines.onDrop(dragIndex, hoverIndex);
-      }
-    }
-  },
-  hover(props, monitor, component) {
-    Common.assertNotNull(props);
-    Common.assertNotNull(monitor);
-    if (component) {
-      const decorated = component.getDecoratedComponentInstance();
-      if (decorated) {
-        const lifelines = decorated.props.lifelines;
-        if (lifelines) {
-          lifelines.setHoverIndex(decorated.props.index);
+    drop(props, monitor, component) {
+        Common.assertNotNull(props);
+        Common.assertNotNull(monitor);
+        const decorated = component.getDecoratedComponentInstance();
+        if (decorated) {
+            const lifelines = decorated.props.lifelines;
+            if (lifelines) {
+                const dragIndex = monitor.getItem().index;
+                const hoverIndex = lifelines.getHoverIndex();
+                lifelines.onDrop(dragIndex, hoverIndex);
+            }
+        }
+    },
+    hover(props, monitor, component) {
+        Common.assertNotNull(props);
+        Common.assertNotNull(monitor);
+        if (component) {
+            const decorated = component.getDecoratedComponentInstance();
+            if (decorated) {
+                const lifelines = decorated.props.lifelines;
+                if (lifelines) {
+                    lifelines.setHoverIndex(decorated.props.index);
+                }
+            }
         }
-      }
     }
-  },
 };
 
 /** DND. */
 function targetCollect(connect, monitor) {
-  return {
-    connectDropTarget: connect.dropTarget(),
-    isOver: monitor.isOver(),
-  };
+    return {
+        connectDropTarget: connect.dropTarget(),
+        isOver: monitor.isOver()
+    };
 }
-
+/* eslint-disable new-cap */
 const wrapper1 = DragSource('lifeline', source, sourceCollect)(Lifeline);
-export default DropTarget(['lifeline', 'lifeline-new'], target, targetCollect)(wrapper1);
+export default DropTarget(['lifeline', 'lifeline-new'], target, targetCollect)(
+    wrapper1
+);
+/* eslint-enable new-cap */
index a8147be..beb6364 100644 (file)
@@ -26,88 +26,92 @@ import iconHandle from '../../../../../../../../../../res/ecomp/asdc/sequencer/s
  * LHS lifeline row view.
  */
 class LifelineNew extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
+        // Bindings.
 
-    // Bindings.
+        this.onClickAdd = this.onClickAdd.bind(this);
+    }
 
-    this.onClickAdd = this.onClickAdd.bind(this);
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Handle click event.
+     */
+    onClickAdd() {
+        this.props.designer.addLifeline();
+    }
 
-  /**
-   * Handle click event.
-   */
-  onClickAdd() {
-    this.props.designer.addLifeline();
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render view.
-   * @returns {*}
-   */
-  render() {
-    const { connectDragSource } = this.props;
-    return connectDragSource(
-      <div className="asdcs-designer-lifeline asdcs-designer-lifeline-new">
-        <table className="asdcs-designer-layout asdcs-designer-lifeline-new">
-          <tbody>
-            <tr>
-              <td>
-                <div className="asdcs-designer-sort asdcs-designer-icon">
-                  <Icon glyph={iconHandle} />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-label" onClick={this.onClickAdd}>
-                  Add Lifeline
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-icon" onClick={this.onClickAdd}>
-                  <Icon glyph={iconPlus} />
-                </div>
-              </td>
-              <td>&nbsp;</td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    );
-  }
+    /**
+     * Render view.
+     * @returns {*}
+     */
+    render() {
+        const { connectDragSource } = this.props;
+        return connectDragSource(
+            <div className="asdcs-designer-lifeline asdcs-designer-lifeline-new">
+                <table className="asdcs-designer-layout asdcs-designer-lifeline-new">
+                    <tbody>
+                        <tr>
+                            <td>
+                                <div className="asdcs-designer-sort asdcs-designer-icon">
+                                    <Icon glyph={iconHandle} />
+                                </div>
+                            </td>
+                            <td>
+                                <div
+                                    className="asdcs-designer-label"
+                                    onClick={this.onClickAdd}>
+                                    Add Lifeline
+                                </div>
+                            </td>
+                            <td>
+                                <div
+                                    className="asdcs-designer-icon"
+                                    onClick={this.onClickAdd}>
+                                    <Icon glyph={iconPlus} />
+                                </div>
+                            </td>
+                            <td>&nbsp;</td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        );
+    }
 }
 
 /** Element properties. */
 LifelineNew.propTypes = {
-  designer: PropTypes.object.isRequired,
-  lifelines: PropTypes.object.isRequired,
-  connectDragSource: PropTypes.func.isRequired,
+    designer: PropTypes.object.isRequired,
+    lifelines: PropTypes.object.isRequired,
+    connectDragSource: PropTypes.func.isRequired
 };
 
 /** DND. */
 const source = {
-  beginDrag(props) {
-    return { id: props.id };
-  },
+    beginDrag(props) {
+        return { id: props.id };
+    }
 };
 
 /** DND. */
 const collect = function collection(connect, monitor) {
-  return {
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging(),
-  };
+    return {
+        connectDragSource: connect.dragSource(),
+        isDragging: monitor.isDragging()
+    };
 };
-
+/* eslint-disable new-cap */
 export default DragSource('lifeline-new', source, collect)(LifelineNew);
+/* eslint-enable new-cap */
index 2f82fec..248264b 100644 (file)
@@ -28,111 +28,110 @@ import LifelineNew from './LifelineNew';
  * @constructor
  */
 class Lifelines extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.setHoverIndex = this.setHoverIndex.bind(this);
+        this.getHoverIndex = this.getHoverIndex.bind(this);
+        this.onDrop = this.onDrop.bind(this);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.setHoverIndex = this.setHoverIndex.bind(this);
-    this.getHoverIndex = this.getHoverIndex.bind(this);
-    this.onDrop = this.onDrop.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Record last hover index as non-state.
-   * @param index index.
-   */
-  setHoverIndex(index) {
-    this.hoverIndex = index;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get last recorded hover index.
-   * @returns {*}
-   */
-  getHoverIndex() {
-    return this.hoverIndex;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle drop.
-   * @param dragIndex dragged item index; undefined if new.
-   * @param hoverIndex drop index.
-   */
-  onDrop(dragIndex, hoverIndex) {
-    if (hoverIndex >= 0) {
-      const application = this.props.application;
-      const model = application.getModel();
-      if (Common.isNumber(dragIndex)) {
-        if (dragIndex !== hoverIndex) {
-          model.reorderLifelines(dragIndex, hoverIndex);
-        }
-      } else {
-        model.addLifeline(hoverIndex);
-      }
-      this.forceUpdate();
-      application.renderDiagram();
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Record last hover index as non-state.
+     * @param index index.
+     */
+    setHoverIndex(index) {
+        this.hoverIndex = index;
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get last recorded hover index.
+     * @returns {*}
+     */
+    getHoverIndex() {
+        return this.hoverIndex;
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render view.
-   * @returns {XML}
-   */
-  render() {
-    const model = this.props.application.getModel();
-    const metamodel = model.getMetamodel();
-    const diagram = model.unwrap().diagram;
-
-    const lifelines = [];
-    for (const lifeline of diagram.lifelines) {
-      lifelines.push(<Lifeline
-        key={`l${lifeline.id}`}
-        application={this.props.application}
-        designer={this.props.designer}
-        lifeline={lifeline}
-        active={this.props.activeLifelineId === lifeline.id}
-        id={lifeline.id}
-        metamodel={metamodel}
-        lifelines={this}
-        index={lifelines.length}
-      />);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle drop.
+     * @param dragIndex dragged item index; undefined if new.
+     * @param hoverIndex drop index.
+     */
+    onDrop(dragIndex, hoverIndex) {
+        if (hoverIndex >= 0) {
+            const application = this.props.application;
+            const model = application.getModel();
+            if (Common.isNumber(dragIndex)) {
+                if (dragIndex !== hoverIndex) {
+                    model.reorderLifelines(dragIndex, hoverIndex);
+                }
+            } else {
+                model.addLifeline(hoverIndex);
+            }
+            this.forceUpdate();
+            application.renderDiagram();
+        }
     }
 
-    lifelines.push(<LifelineNew
-      key="_l"
-      designer={this.props.designer}
-      lifelines={this}
-    />);
-
-    return (
-      <div className="asdcs-designer-lifelines">
-        {lifelines}
-      </div>
-    );
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render view.
+     * @returns {XML}
+     */
+    render() {
+        const model = this.props.application.getModel();
+        const metamodel = model.getMetamodel();
+        const diagram = model.unwrap().diagram;
+
+        const lifelines = [];
+        for (const lifeline of diagram.lifelines) {
+            lifelines.push(
+                <Lifeline
+                    key={`l${lifeline.id}`}
+                    application={this.props.application}
+                    designer={this.props.designer}
+                    lifeline={lifeline}
+                    active={this.props.activeLifelineId === lifeline.id}
+                    id={lifeline.id}
+                    metamodel={metamodel}
+                    lifelines={this}
+                    index={lifelines.length}
+                />
+            );
+        }
+
+        lifelines.push(
+            <LifelineNew
+                key="_l"
+                designer={this.props.designer}
+                lifelines={this}
+            />
+        );
+
+        return <div className="asdcs-designer-lifelines">{lifelines}</div>;
+    }
 }
 
 /**
  * Declare properties.
  */
 Lifelines.propTypes = {
-  application: PropTypes.object.isRequired,
-  designer: PropTypes.object.isRequired,
-  activeLifelineId: PropTypes.string,
+    application: PropTypes.object.isRequired,
+    designer: PropTypes.object.isRequired,
+    activeLifelineId: PropTypes.string
 };
 
 export default Lifelines;
index a2c7f51..ba77e86 100644 (file)
@@ -34,482 +34,480 @@ import iconResponse from '../../../../../../../../../../res/ecomp/asdc/sequencer
  * LHS message row view.
  */
 class Message extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+
+        this.state = {
+            active: false,
+            name: props.message.name || ''
+        };
+
+        this.combinedOptions = [
+            {
+                value: 'REQUEST_SYNC'
+            },
+            {
+                value: 'REQUEST_ASYNC'
+            },
+            {
+                value: 'RESPONSE'
+            }
+        ];
+
+        // Bindings.
+
+        this.onChangeName = this.onChangeName.bind(this);
+        this.onBlurName = this.onBlurName.bind(this);
+        this.onChangeType = this.onChangeType.bind(this);
+        this.onChangeFrom = this.onChangeFrom.bind(this);
+        this.onChangeTo = this.onChangeTo.bind(this);
+        this.onClickDelete = this.onClickDelete.bind(this);
+        this.onClickActions = this.onClickActions.bind(this);
+        this.onClickNotes = this.onClickNotes.bind(this);
+        this.onMouseEnter = this.onMouseEnter.bind(this);
+        this.onMouseLeave = this.onMouseLeave.bind(this);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
+    /**
+     * Handle name change.
+     * @param event change event.
+     */
+    onChangeName(event) {
+        this.setState({ name: event.target.value });
+    }
 
-    this.state = {
-      active: false,
-      name: props.message.name || '',
-    };
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle name change.
+     * @param event change event.
+     */
+    onBlurName(event) {
+        const options = this.props.application.getOptions();
+        const sanitized = Common.sanitizeText(
+            event.target.value,
+            options,
+            'message'
+        );
+        const props = {
+            id: this.props.message.id,
+            name: sanitized
+        };
+        this.props.designer.updateMessage(props);
+        this.setState({ name: sanitized });
+    }
 
-    this.combinedOptions = [{
-      value: 'REQUEST_SYNC',
-    }, {
-      value: 'REQUEST_ASYNC',
-    }, {
-      value: 'RESPONSE',
-    }];
-
-    // Bindings.
-
-    this.onChangeName = this.onChangeName.bind(this);
-    this.onBlurName = this.onBlurName.bind(this);
-    this.onChangeType = this.onChangeType.bind(this);
-    this.onChangeFrom = this.onChangeFrom.bind(this);
-    this.onChangeTo = this.onChangeTo.bind(this);
-    this.onClickDelete = this.onClickDelete.bind(this);
-    this.onClickActions = this.onClickActions.bind(this);
-    this.onClickNotes = this.onClickNotes.bind(this);
-    this.onMouseEnter = this.onMouseEnter.bind(this);
-    this.onMouseLeave = this.onMouseLeave.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle name change.
-   * @param event change event.
-   */
-  onChangeName(event) {
-    this.setState({ name: event.target.value });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle name change.
-   * @param event change event.
-   */
-  onBlurName(event) {
-    const options = this.props.application.getOptions();
-    const sanitized = Common.sanitizeText(event.target.value, options, 'message');
-    const props = {
-      id: this.props.message.id,
-      name: sanitized,
-    };
-    this.props.designer.updateMessage(props);
-    this.setState({ name: sanitized });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle delete.
-   */
-  onClickDelete() {
-    this.props.designer.deleteMessage(this.props.message.id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle menu click.
-   */
-  onClickActions(event) {
-    this.props.designer.showActions(this.props.message.id, { x: event.pageX, y: event.pageY });
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle menu click.
-   */
-  onClickNotes() {
-    this.props.designer.showNotes(this.props.message.id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle selection.
-   * @param value selection.
-   */
-  onChangeFrom(value) {
-    if (value.target) {
-      this.updateMessage({ from: value.target.value });
-    } else {
-      this.updateMessage({ from: value.value });
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle delete.
+     */
+    onClickDelete() {
+        this.props.designer.deleteMessage(this.props.message.id);
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle selection.
-   * @param value selection.
-   */
-  onChangeTo(value) {
-    if (value.target) {
-      this.updateMessage({ to: value.target.value });
-    } else {
-      this.updateMessage({ to: value.value });
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     */
+    onClickActions(event) {
+        this.props.designer.showActions(this.props.message.id, {
+            x: event.pageX,
+            y: event.pageY
+        });
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle selection.
-   * @param selected selection.
-   */
-  onChangeType(selected) {
-
-    const value = selected.target ? selected.target.value : selected.value;
-    const props = {};
-    if (value.indexOf('RESPONSE') !== -1) {
-      props.type = 'response';
-      props.asynchronous = false;
-    } else {
-      props.type = 'request';
-      props.asynchronous = (value.indexOf('ASYNC') !== -1);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle menu click.
+     */
+    onClickNotes() {
+        this.props.designer.showNotes(this.props.message.id);
     }
 
-    this.updateMessage(props);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   */
-  onMouseEnter() {
-    this.setState({ active: true });
-    this.props.designer.onMouseEnterMessage(this.props.message.id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle mouse event.
-   */
-  onMouseLeave() {
-    this.setState({ active: false });
-    this.props.designer.onMouseLeaveMessage(this.props.message.id);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Update message properties.
-   * @param props properties updates.
-   */
-  updateMessage(props) {
-    const update = {
-      id: this.props.message.id,
-    };
-    for (const k of Object.keys(props)) {
-      update[k] = props[k];
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle selection.
+     * @param value selection.
+     */
+    onChangeFrom(value) {
+        if (value.target) {
+            this.updateMessage({ from: value.target.value });
+        } else {
+            this.updateMessage({ from: value.value });
+        }
     }
-    this.props.designer.updateMessage(update);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render icon.
-   * @param option selection.
-   * @returns {XML}
-   */
-  renderOption(option) {
-    if (option.value === 'RESPONSE') {
-      return <Icon glyph={iconResponse} />;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle selection.
+     * @param value selection.
+     */
+    onChangeTo(value) {
+        if (value.target) {
+            this.updateMessage({ to: value.target.value });
+        } else {
+            this.updateMessage({ to: value.value });
+        }
     }
-    if (option.value === 'REQUEST_ASYNC') {
-      return <Icon glyph={iconRequestAsync} />;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle selection.
+     * @param selected selection.
+     */
+    onChangeType(selected) {
+        const value = selected.target ? selected.target.value : selected.value;
+        const props = {};
+        if (value.indexOf('RESPONSE') !== -1) {
+            props.type = 'response';
+            props.asynchronous = false;
+        } else {
+            props.type = 'request';
+            props.asynchronous = value.indexOf('ASYNC') !== -1;
+        }
+
+        this.updateMessage(props);
     }
-    return <Icon glyph={iconRequestSync} />;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get request/response and asynchronous combined constant.
-   * @param message message whose properties define spec.
-   * @returns {*}
-   */
-  getMessageSpec(message) {
-    if (message.type === 'response') {
-      return 'RESPONSE';
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle mouse event.
+     */
+    onMouseEnter() {
+        this.setState({ active: true });
+        this.props.designer.onMouseEnterMessage(this.props.message.id);
     }
-    if (message.asynchronous) {
-      return 'REQUEST_ASYNC';
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle mouse event.
+     */
+    onMouseLeave() {
+        this.setState({ active: false });
+        this.props.designer.onMouseLeaveMessage(this.props.message.id);
     }
-    return 'REQUEST_SYNC';
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * @returns {*}
-   * @private
-   */
-  renderHTMLSelect() {
-
-    const message = this.props.message;
-    const from = this.props.from;
-    const to = Common.assertNotNull(this.props.to);
-    const messageNotesActiveClass = message.notes && message.notes.length > 0 ? 'asdcs-active' : '';
-    const combinedValue = this.getMessageSpec(message);
-
-    const lifelineOptions = [];
-    for (const lifeline of this.props.model.unwrap().diagram.lifelines) {
-      lifelineOptions.push(<option
-        key={lifeline.id}
-        value={lifeline.id}
-      >
-        {lifeline.name}
-      </option>);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Update message properties.
+     * @param props properties updates.
+     */
+    updateMessage(props) {
+        const update = {
+            id: this.props.message.id
+        };
+        for (const k of Object.keys(props)) {
+            update[k] = props[k];
+        }
+        this.props.designer.updateMessage(update);
     }
 
-    const activeClass = (this.state.active || this.props.active) ? 'asdcs-active' : '';
-    const { connectDragSource, connectDropTarget } = this.props;
-    return connectDragSource(connectDropTarget(
-      <div
-        className={`asdcs-designer-message ${activeClass}`}
-        data-id={message.id}
-        onMouseEnter={this.onMouseEnter}
-        onMouseLeave={this.onMouseLeave}
-      >
-
-        <table className="asdcs-designer-layout asdcs-designer-message-row1">
-          <tbody>
-            <tr>
-              <td>
-                <div className="asdcs-designer-sort asdcs-designer-icon">
-                  <Icon glyph={iconHandle} />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-message-index">{message.index}.</div>
-              </td>
-              <td>
-                <div className="asdcs-designer-message-name">
-                  <input
-                    type="text"
-                    className="asdcs-editable"
-                    value={this.state.name}
-                    placeholder="Unnamed"
-                    onBlur={this.onBlurName}
-                    onChange={this.onChangeName}
-                  />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-actions">
-                  <div
-                    className="asdcs-designer-settings asdcs-designer-icon"
-                    onClick={this.onClickActions}
-                  >
-                    <Icon glyph={iconSettings} />
-                  </div>
-                  <div
-                    className={`asdcs-designer-notes asdcs-designer-icon ${messageNotesActiveClass}`}
-                    onClick={this.onClickNotes}
-                  >
-                    <Icon glyph={iconNotes} />
-                  </div>
-                  <div
-                    className="asdcs-designer-delete asdcs-designer-icon"
-                    onClick={this.onClickDelete}
-                  >
-                    <Icon glyph={iconDelete} />
-                  </div>
-                </div>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-
-        <table className="asdcs-designer-layout asdcs-designer-message-row2">
-          <tbody>
-            <tr>
-              <td>
-                <select
-                  onChange={this.onChangeFrom}
-                  className="asdcs-designer-select-message-from"
-                  value={from.id}
-                  onChange={this.onChangeFrom}
-                >
-                  options={lifelineOptions}
-                </select>
-              </td>
-              <td>
-                <select
-                  onChange={this.onChangeFrom}
-                  className="asdcs-designer-select-message-type"
-                  value={combinedValue}
-                  onChange={this.onChangeType}
-                >
-                  <option value="REQUEST_SYNC">⇾</option>
-                  <option value="REQUEST_ASYNC">→</option>
-                  <option value="RESPONSE">⇠</option>
-                </select>
-              </td>
-              <td>
-                <select
-                  onChange={this.onChangeFrom}
-                  className="asdcs-designer-select-message-to"
-                  value={to.id}
-                  onChange={this.onChangeTo}
-                >
-                  options={lifelineOptions}
-                </select>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-
-      </div>
-    ));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render view.
-   * @returns {*}
-   * @private
-   */
-  renderReactSelect() {
-
-    const message = this.props.message;
-    const from = this.props.from;
-    const to = Common.assertNotNull(this.props.to);
-    const messageNotesActiveClass = message.notes && message.notes.length > 0 ? 'asdcs-active' : '';
-    const combinedValue = this.getMessageSpec(message);
-
-    const lifelineOptions = [];
-    for (const lifeline of this.props.model.unwrap().diagram.lifelines) {
-      lifelineOptions.push({
-        value: lifeline.id,
-        label: lifeline.name,
-      });
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render icon.
+     * @param option selection.
+     * @returns {XML}
+     */
+    renderOption(option) {
+        if (option.value === 'RESPONSE') {
+            return <Icon glyph={iconResponse} />;
+        }
+        if (option.value === 'REQUEST_ASYNC') {
+            return <Icon glyph={iconRequestAsync} />;
+        }
+        return <Icon glyph={iconRequestSync} />;
     }
 
-    const activeClass = (this.state.active || this.props.active) ? 'asdcs-active' : '';
-    const { connectDragSource, connectDropTarget } = this.props;
-    return connectDragSource(connectDropTarget(
-
-      <div
-        className={`asdcs-designer-message ${activeClass}`}
-        data-id={message.id}
-        onMouseEnter={this.onMouseEnter}
-        onMouseLeave={this.onMouseLeave}
-      >
-
-        <table className="asdcs-designer-layout asdcs-designer-message-row1">
-          <tbody>
-            <tr>
-              <td>
-                <div className="asdcs-designer-sort asdcs-designer-icon">
-                  <Icon glyph={iconHandle} />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-message-index">{message.index}.</div>
-              </td>
-              <td>
-                <div className="asdcs-designer-message-name">
-                  <input
-                    type="text"
-                    className="asdcs-editable"
-                    value={this.state.name}
-                    placeholder="Unnamed"
-                    onBlur={this.onBlurName}
-                    onChange={this.onChangeName}
-                  />
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get request/response and asynchronous combined constant.
+     * @param message message whose properties define spec.
+     * @returns {*}
+     */
+    getMessageSpec(message) {
+        if (message.type === 'response') {
+            return 'RESPONSE';
+        }
+        if (message.asynchronous) {
+            return 'REQUEST_ASYNC';
+        }
+        return 'REQUEST_SYNC';
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * @returns {*}
+     * @private
+     */
+    renderHTMLSelect() {
+        const message = this.props.message;
+        const from = this.props.from;
+        const to = Common.assertNotNull(this.props.to);
+        const messageNotesActiveClass =
+            message.notes && message.notes.length > 0 ? 'asdcs-active' : '';
+        const combinedValue = this.getMessageSpec(message);
+
+        const lifelineOptions = [];
+        for (const lifeline of this.props.model.unwrap().diagram.lifelines) {
+            lifelineOptions.push(
+                <option key={lifeline.id} value={lifeline.id}>
+                    {lifeline.name}
+                </option>
+            );
+        }
+
+        const activeClass =
+            this.state.active || this.props.active ? 'asdcs-active' : '';
+        const { connectDragSource, connectDropTarget } = this.props;
+        return connectDragSource(
+            connectDropTarget(
+                <div
+                    className={`asdcs-designer-message ${activeClass}`}
+                    data-id={message.id}
+                    onMouseEnter={this.onMouseEnter}
+                    onMouseLeave={this.onMouseLeave}>
+                    <table className="asdcs-designer-layout asdcs-designer-message-row1">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div className="asdcs-designer-sort asdcs-designer-icon">
+                                        <Icon glyph={iconHandle} />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-message-index">
+                                        {message.index}.
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-message-name">
+                                        <input
+                                            type="text"
+                                            className="asdcs-editable"
+                                            value={this.state.name}
+                                            placeholder="Unnamed"
+                                            onBlur={this.onBlurName}
+                                            onChange={this.onChangeName}
+                                        />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-actions">
+                                        <div
+                                            className="asdcs-designer-settings asdcs-designer-icon"
+                                            onClick={this.onClickActions}>
+                                            <Icon glyph={iconSettings} />
+                                        </div>
+                                        <div
+                                            className={`asdcs-designer-notes asdcs-designer-icon ${messageNotesActiveClass}`}
+                                            onClick={this.onClickNotes}>
+                                            <Icon glyph={iconNotes} />
+                                        </div>
+                                        <div
+                                            className="asdcs-designer-delete asdcs-designer-icon"
+                                            onClick={this.onClickDelete}>
+                                            <Icon glyph={iconDelete} />
+                                        </div>
+                                    </div>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+
+                    <table className="asdcs-designer-layout asdcs-designer-message-row2">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <select
+                                        className="asdcs-designer-select-message-from"
+                                        value={from.id}
+                                        onChange={this.onChangeFrom}>
+                                        options={lifelineOptions}
+                                    </select>
+                                </td>
+                                <td>
+                                    <select
+                                        className="asdcs-designer-select-message-type"
+                                        value={combinedValue}
+                                        onChange={this.onChangeType}>
+                                        <option value="REQUEST_SYNC">⇾</option>
+                                        <option value="REQUEST_ASYNC">→</option>
+                                        <option value="RESPONSE">⇠</option>
+                                    </select>
+                                </td>
+                                <td>
+                                    <select
+                                        className="asdcs-designer-select-message-to"
+                                        value={to.id}
+                                        onChange={this.onChangeTo}>
+                                        options={lifelineOptions}
+                                    </select>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
                 </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-actions">
-                  <div
-                    className="asdcs-designer-settings asdcs-designer-icon"
-                    onClick={this.onClickActions}
-                  >
-                    <Icon glyph={iconSettings} />
-                  </div>
-                  <div
-                    className={`asdcs-designer-notes asdcs-designer-icon ${messageNotesActiveClass}`}
-                    onClick={this.onClickNotes}
-                  >
-                    <Icon glyph={iconNotes} />
-                  </div>
-                  <div
-                    className="asdcs-designer-delete asdcs-designer-icon"
-                    onClick={this.onClickDelete}
-                  >
-                    <Icon glyph={iconDelete} />
-                  </div>
+            )
+        );
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render view.
+     * @returns {*}
+     * @private
+     */
+    renderReactSelect() {
+        const message = this.props.message;
+        const from = this.props.from;
+        const to = Common.assertNotNull(this.props.to);
+        const messageNotesActiveClass =
+            message.notes && message.notes.length > 0 ? 'asdcs-active' : '';
+        const combinedValue = this.getMessageSpec(message);
+
+        const lifelineOptions = [];
+        for (const lifeline of this.props.model.unwrap().diagram.lifelines) {
+            lifelineOptions.push({
+                value: lifeline.id,
+                label: lifeline.name
+            });
+        }
+
+        const activeClass =
+            this.state.active || this.props.active ? 'asdcs-active' : '';
+        const { connectDragSource, connectDropTarget } = this.props;
+        return connectDragSource(
+            connectDropTarget(
+                <div
+                    className={`asdcs-designer-message ${activeClass}`}
+                    data-id={message.id}
+                    onMouseEnter={this.onMouseEnter}
+                    onMouseLeave={this.onMouseLeave}>
+                    <table className="asdcs-designer-layout asdcs-designer-message-row1">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div className="asdcs-designer-sort asdcs-designer-icon">
+                                        <Icon glyph={iconHandle} />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-message-index">
+                                        {message.index}.
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-message-name">
+                                        <input
+                                            type="text"
+                                            className="asdcs-editable"
+                                            value={this.state.name}
+                                            placeholder="Unnamed"
+                                            onBlur={this.onBlurName}
+                                            onChange={this.onChangeName}
+                                        />
+                                    </div>
+                                </td>
+                                <td>
+                                    <div className="asdcs-designer-actions">
+                                        <div
+                                            className="asdcs-designer-settings asdcs-designer-icon"
+                                            onClick={this.onClickActions}>
+                                            <Icon glyph={iconSettings} />
+                                        </div>
+                                        <div
+                                            className={`asdcs-designer-notes asdcs-designer-icon ${messageNotesActiveClass}`}
+                                            onClick={this.onClickNotes}>
+                                            <Icon glyph={iconNotes} />
+                                        </div>
+                                        <div
+                                            className="asdcs-designer-delete asdcs-designer-icon"
+                                            onClick={this.onClickDelete}>
+                                            <Icon glyph={iconDelete} />
+                                        </div>
+                                    </div>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+
+                    <table className="asdcs-designer-layout asdcs-designer-message-row2">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <Select
+                                        className="asdcs-editable-select asdcs-designer-editable-message-from"
+                                        openOnFocus
+                                        clearable={false}
+                                        searchable={false}
+                                        value={from.id}
+                                        onChange={this.onChangeFrom}
+                                        options={lifelineOptions}
+                                    />
+                                </td>
+                                <td>
+                                    <Select
+                                        className="asdcs-editable-select asdcs-designer-editable-message-type"
+                                        openOnFocus
+                                        clearable={false}
+                                        searchable={false}
+                                        value={combinedValue}
+                                        onChange={this.onChangeType}
+                                        options={this.combinedOptions}
+                                        optionRenderer={this.renderOption}
+                                        valueRenderer={this.renderOption}
+                                    />
+                                </td>
+                                <td>
+                                    <Select
+                                        className="asdcs-editable-select asdcs-designer-editable-message-to"
+                                        openOnFocus
+                                        clearable={false}
+                                        searchable={false}
+                                        value={to.id}
+                                        onChange={this.onChangeTo}
+                                        options={lifelineOptions}
+                                    />
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
                 </div>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-
-        <table className="asdcs-designer-layout asdcs-designer-message-row2">
-          <tbody>
-            <tr>
-              <td>
-                <Select
-                  className="asdcs-editable-select asdcs-designer-editable-message-from"
-                  openOnFocus
-                  clearable={false}
-                  searchable={false}
-                  value={from.id}
-                  onChange={this.onChangeFrom}
-                  options={lifelineOptions}
-                />
-              </td>
-              <td>
-                <Select
-                  className="asdcs-editable-select asdcs-designer-editable-message-type"
-                  openOnFocus
-                  clearable={false}
-                  searchable={false}
-                  value={combinedValue}
-                  onChange={this.onChangeType}
-                  options={this.combinedOptions}
-                  optionRenderer={this.renderOption}
-                  valueRenderer={this.renderOption}
-                />
-              </td>
-              <td>
-                <Select
-                  className="asdcs-editable-select asdcs-designer-editable-message-to"
-                  openOnFocus
-                  clearable={false}
-                  searchable={false}
-                  value={to.id}
-                  onChange={this.onChangeTo}
-                  options={lifelineOptions}
-                />
-              </td>
-
-            </tr>
-          </tbody>
-        </table>
-
-      </div>
-    ));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  render() {
-    const options = this.props.application.getOptions();
-    if (options.useHtmlSelect) {
-      return this.renderHTMLSelect();
+            )
+        );
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    render() {
+        const options = this.props.application.getOptions();
+        if (options.useHtmlSelect) {
+            return this.renderHTMLSelect();
+        }
+        return this.renderReactSelect();
     }
-    return this.renderReactSelect();
-  }
 }
 
 /**
@@ -517,72 +515,74 @@ class Message extends React.Component {
  * @type {{designer: *, message: *, from: *, to: *, model: *, connectDragSource: *}}
  */
 Message.propTypes = {
-  application: PropTypes.object.isRequired,
-  designer: PropTypes.object.isRequired,
-  message: PropTypes.object.isRequired,
-  active: PropTypes.bool.isRequired,
-  from: PropTypes.object.isRequired,
-  to: PropTypes.object.isRequired,
-  model: PropTypes.object.isRequired,
-  index: PropTypes.number.isRequired,
-  messages: PropTypes.object.isRequired,
-  connectDragSource: PropTypes.func.isRequired,
-  connectDropTarget: PropTypes.func.isRequired,
+    application: PropTypes.object.isRequired,
+    designer: PropTypes.object.isRequired,
+    message: PropTypes.object.isRequired,
+    active: PropTypes.bool.isRequired,
+    from: PropTypes.object.isRequired,
+    to: PropTypes.object.isRequired,
+    model: PropTypes.object.isRequired,
+    index: PropTypes.number.isRequired,
+    messages: PropTypes.object.isRequired,
+    connectDragSource: PropTypes.func.isRequired,
+    connectDropTarget: PropTypes.func.isRequired
 };
 
 /** DND. */
 const source = {
-  beginDrag(props) {
-    return {
-      id: props.id,
-      index: props.index,
-    };
-  },
+    beginDrag(props) {
+        return {
+            id: props.id,
+            index: props.index
+        };
+    }
 };
 
 /** DND. */
 const sourceCollect = function collection(connect, monitor) {
-  return {
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging(),
-  };
+    return {
+        connectDragSource: connect.dragSource(),
+        isDragging: monitor.isDragging()
+    };
 };
 
-
 /** DND. */
 const target = {
-  drop(props, monitor, component) {
-    Common.assertNotNull(props);
-    Common.assertNotNull(monitor);
-    const decorated = component.getDecoratedComponentInstance();
-    if (decorated) {
-      const messages = decorated.props.messages;
-      if (messages) {
-        const dragIndex = monitor.getItem().index;
-        const hoverIndex = messages.getHoverIndex();
-        messages.onDrop(dragIndex, hoverIndex);
-      }
+    drop(props, monitor, component) {
+        Common.assertNotNull(props);
+        Common.assertNotNull(monitor);
+        const decorated = component.getDecoratedComponentInstance();
+        if (decorated) {
+            const messages = decorated.props.messages;
+            if (messages) {
+                const dragIndex = monitor.getItem().index;
+                const hoverIndex = messages.getHoverIndex();
+                messages.onDrop(dragIndex, hoverIndex);
+            }
+        }
+    },
+    hover(props, monitor, component) {
+        Common.assertNotNull(props);
+        Common.assertNotNull(monitor);
+        if (component) {
+            const decorated = component.getDecoratedComponentInstance();
+            if (decorated) {
+                decorated.props.messages.setHoverIndex(decorated.props.index);
+            }
+        }
     }
-  },
-  hover(props, monitor, component) {
-    Common.assertNotNull(props);
-    Common.assertNotNull(monitor);
-    if (component) {
-      const decorated = component.getDecoratedComponentInstance();
-      if (decorated) {
-        decorated.props.messages.setHoverIndex(decorated.props.index);
-      }
-    }
-  },
 };
 
 /** DND. */
 function targetCollect(connect, monitor) {
-  return {
-    connectDropTarget: connect.dropTarget(),
-    isOver: monitor.isOver(),
-  };
+    return {
+        connectDropTarget: connect.dropTarget(),
+        isOver: monitor.isOver()
+    };
 }
-
+/* eslint-disable new-cap */
 const wrapper = DragSource('message', source, sourceCollect)(Message);
-export default DropTarget(['message', 'message-new'], target, targetCollect)(wrapper);
+export default DropTarget(['message', 'message-new'], target, targetCollect)(
+    wrapper
+);
+/* eslint-enable new-cap */
index c47cf28..78e892b 100644 (file)
@@ -26,82 +26,84 @@ import iconHandle from '../../../../../../../../../../res/ecomp/asdc/sequencer/s
  * LHS lifeline row view.
  */
 class MessageNew extends React.Component {
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.onClickAdd = this.onClickAdd.bind(this);
+    }
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.onClickAdd = this.onClickAdd.bind(this);
-  }
+    /**
+     * Handle add.
+     */
+    onClickAdd() {
+        this.props.designer.addMessage();
+    }
 
-  /**
-   * Handle add.
-   */
-  onClickAdd() {
-    this.props.designer.addMessage();
-  }
-
-  /**
-   * Render view.
-   * @returns {*}
-   */
-  render() {
-    const { connectDragSource } = this.props;
-    return connectDragSource(
-      <div className="asdcs-designer-message asdcs-designer-message-new">
-        <table className="asdcs-designer-layout asdcs-designer-message-new">
-          <tbody>
-            <tr>
-              <td>
-                <div className="asdcs-designer-sort asdcs-designer-icon">
-                  <Icon glyph={iconHandle} />
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-label" onClick={this.onClickAdd}>
-                  Add Message
-                </div>
-              </td>
-              <td>
-                <div className="asdcs-designer-icon" onClick={this.onClickAdd}>
-                  <Icon glyph={iconPlus} />
-                </div>
-              </td>
-              <td>
-                &nbsp;
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    );
-  }
+    /**
+     * Render view.
+     * @returns {*}
+     */
+    render() {
+        const { connectDragSource } = this.props;
+        return connectDragSource(
+            <div className="asdcs-designer-message asdcs-designer-message-new">
+                <table className="asdcs-designer-layout asdcs-designer-message-new">
+                    <tbody>
+                        <tr>
+                            <td>
+                                <div className="asdcs-designer-sort asdcs-designer-icon">
+                                    <Icon glyph={iconHandle} />
+                                </div>
+                            </td>
+                            <td>
+                                <div
+                                    className="asdcs-designer-label"
+                                    onClick={this.onClickAdd}>
+                                    Add Message
+                                </div>
+                            </td>
+                            <td>
+                                <div
+                                    className="asdcs-designer-icon"
+                                    onClick={this.onClickAdd}>
+                                    <Icon glyph={iconPlus} />
+                                </div>
+                            </td>
+                            <td>&nbsp;</td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        );
+    }
 }
 
 /** Element properties. */
 MessageNew.propTypes = {
-  designer: PropTypes.object.isRequired,
-  messages: PropTypes.object.isRequired,
-  connectDragSource: PropTypes.func.isRequired,
+    designer: PropTypes.object.isRequired,
+    messages: PropTypes.object.isRequired,
+    connectDragSource: PropTypes.func.isRequired
 };
 
 /** DND. */
 const source = {
-  beginDrag(props) {
-    return { id: props.id };
-  },
+    beginDrag(props) {
+        return { id: props.id };
+    }
 };
 
 /** DND. */
 const collect = function collection(connect, monitor) {
-  return {
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging(),
-  };
+    return {
+        connectDragSource: connect.dragSource(),
+        isDragging: monitor.isDragging()
+    };
 };
 
+/* eslint-disable new-cap */
 export default DragSource('message-new', source, collect)(MessageNew);
-
+/* eslint-enable new-cap */
index 4171554..6d2b35e 100644 (file)
@@ -28,116 +28,113 @@ import MessageNew from './MessageNew';
  * @constructor
  */
 export default class Messages extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.state = {};
+        this.setHoverIndex = this.setHoverIndex.bind(this);
+        this.getHoverIndex = this.getHoverIndex.bind(this);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.state = {
-    };
-    this.setHoverIndex = this.setHoverIndex.bind(this);
-    this.getHoverIndex = this.getHoverIndex.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Record last hover index as non-state.
-   * @param index index.
-   */
-  setHoverIndex(index) {
-    this.hoverIndex = index;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get last recorded hover index.
-   * @returns {*}
-   */
-  getHoverIndex() {
-    return this.hoverIndex;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Handle drop.
-   * @param dragIndex dragged item index; undefined if new.
-   * @param hoverIndex drop index.
-   */
-  onDrop(dragIndex, hoverIndex) {
-    if (hoverIndex >= 0) {
-      const application = this.props.application;
-      const model = application.getModel();
-      if (Common.isNumber(dragIndex)) {
-        if (dragIndex !== hoverIndex) {
-          model.reorderMessages(dragIndex, hoverIndex);
-        }
-      } else {
-        model.addMessage(hoverIndex);
-      }
-      this.forceUpdate();
-      application.renderDiagram();
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Record last hover index as non-state.
+     * @param index index.
+     */
+    setHoverIndex(index) {
+        this.hoverIndex = index;
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render view.
-   * @returns {*}
-   */
-  render() {
-
-    const model = this.props.application.getModel();
-    const diagram = model.unwrap().diagram;
-
-    // Render existing messages.
-
-    const messages = [];
-    for (const step of diagram.steps) {
-      const message = step.message;
-      const from = model.getLifelineById(message.from);
-      const to = model.getLifelineById(message.to);
-      messages.push(<Message
-        key={`m${message.id}`}
-        application={this.props.application}
-        designer={this.props.designer}
-        message={message}
-        active={this.props.activeMessageId === message.id}
-        from={from}
-        to={to}
-        model={model}
-        index={messages.length}
-        messages={this}
-      />);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get last recorded hover index.
+     * @returns {*}
+     */
+    getHoverIndex() {
+        return this.hoverIndex;
     }
 
-    // Render add.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Handle drop.
+     * @param dragIndex dragged item index; undefined if new.
+     * @param hoverIndex drop index.
+     */
+    onDrop(dragIndex, hoverIndex) {
+        if (hoverIndex >= 0) {
+            const application = this.props.application;
+            const model = application.getModel();
+            if (Common.isNumber(dragIndex)) {
+                if (dragIndex !== hoverIndex) {
+                    model.reorderMessages(dragIndex, hoverIndex);
+                }
+            } else {
+                model.addMessage(hoverIndex);
+            }
+            this.forceUpdate();
+            application.renderDiagram();
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render view.
+     * @returns {*}
+     */
+    render() {
+        const model = this.props.application.getModel();
+        const diagram = model.unwrap().diagram;
+
+        // Render existing messages.
+
+        const messages = [];
+        for (const step of diagram.steps) {
+            const message = step.message;
+            const from = model.getLifelineById(message.from);
+            const to = model.getLifelineById(message.to);
+            messages.push(
+                <Message
+                    key={`m${message.id}`}
+                    application={this.props.application}
+                    designer={this.props.designer}
+                    message={message}
+                    active={this.props.activeMessageId === message.id}
+                    from={from}
+                    to={to}
+                    model={model}
+                    index={messages.length}
+                    messages={this}
+                />
+            );
+        }
 
-    messages.push(<MessageNew
-      key="_m"
-      designer={this.props.designer}
-      messages={this}
-    />);
+        // Render add.
 
-    return (
-      <div className="asdcs-designer-steps">
-        {messages}
-      </div>
-    );
-  }
+        messages.push(
+            <MessageNew
+                key="_m"
+                designer={this.props.designer}
+                messages={this}
+            />
+        );
+
+        return <div className="asdcs-designer-steps">{messages}</div>;
+    }
 }
 
 /** Element properties. */
 Messages.propTypes = {
-  application: PropTypes.object.isRequired,
-  designer: PropTypes.object.isRequired,
-  activeMessageId: PropTypes.string,
+    application: PropTypes.object.isRequired,
+    designer: PropTypes.object.isRequired,
+    activeMessageId: PropTypes.string
 };
index cc1fadd..419c728 100644 (file)
@@ -20,15 +20,11 @@ import PropTypes from 'prop-types';
  * Metadata view.
  */
 const Metadata = function Metadata(props) {
-  return (
-    <div className="asdcs-designer-metadata">
-      {props.metadata.name}
-    </div>
-  );
+    return <div className="asdcs-designer-metadata">{props.metadata.name}</div>;
 };
 
 Metadata.propTypes = {
-  metadata: PropTypes.object.isRequired,
+    metadata: PropTypes.object.isRequired
 };
 
 export default Metadata;
index 04ea528..1ba7e9f 100644 (file)
@@ -20,67 +20,69 @@ import PropTypes from 'prop-types';
  * Editor view, aggregating the designer, the code editor, the toolbar.
  */
 export default class Source extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct view.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.demo = this.props.application.getOptions().demo;
-  }
+    /**
+     * Construct view.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.demo = this.props.application.getOptions().demo;
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Set JSON mode.
-   * @param json JSON (stringified) code.
-   */
-  setJSON(json = '') {
-    if (this.textarea) {
-      this.textarea.value = json;
+    /**
+     * Set JSON mode.
+     * @param json JSON (stringified) code.
+     */
+    setJSON(json = '') {
+        if (this.textarea) {
+            this.textarea.value = json;
+        }
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Set YAML mode.
-   * @param yaml YAML code.
-   */
-  setYAML(yaml = '') {
-    if (this.textarea) {
-      this.textarea.value = yaml;
+    /**
+     * Set YAML mode.
+     * @param yaml YAML code.
+     */
+    setYAML(yaml = '') {
+        if (this.textarea) {
+            this.textarea.value = yaml;
+        }
     }
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  componentDidMount() {
-    /*
+    componentDidMount() {
+        /*
     this.cm = CodeMirror.fromTextArea(this.textarea, {
       lineNumbers: true,
       readOnly: true,
     });
     */
-  }
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Render to DOM.
-   */
-  render() {
-    return (
-      <div className="asdcs-editor-code">
-        <textarea ref={(r) => { this.textarea = r; }}></textarea>
-      </div>
-    );
-  }
+    /**
+     * Render to DOM.
+     */
+    render() {
+        return (
+            <div className="asdcs-editor-code">
+                <textarea
+                    ref={r => {
+                        this.textarea = r;
+                    }}
+                />
+            </div>
+        );
+    }
 }
 
 Source.propTypes = {
-  application: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired
 };
-
index 4ac9c3d..c321725 100644 (file)
@@ -26,100 +26,120 @@ import iconOpen from '../../../../../../../../res/ecomp/asdc/sequencer/sprites/i
  * all you get are the buttons for toggling between JSON/YAML/Designer.
  */
 export default class Toolbar extends React.Component {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct view.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.application = Common.assertType(this.props.application, 'Object');
+        this.editor = Common.assertType(this.props.editor, 'Object');
+        this.mode = 'design';
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct view.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.application = Common.assertType(this.props.application, 'Object');
-    this.editor = Common.assertType(this.props.editor, 'Object');
-    this.mode = 'design';
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Set editor mode, one of {design, json, yaml}.
-   * @param mode
-   */
-  setMode(mode = 'design') {
-    this.mode = mode;
-  }
+    /**
+     * Set editor mode, one of {design, json, yaml}.
+     * @param mode
+     */
+    setMode(mode = 'design') {
+        this.mode = mode;
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Render into the DOM.
-   */
-  render() {
-
-    const demo = this.application.getOptions().demo;
-    const demoCss = demo ? '' : 'asdc-hide';
-
-    return (
-      <div className={`asdcs-editor-toolbar ${demoCss}`}>
-        <div className="asdcs-editor-toolbar-demo">
-          <button className="asdcs-button-new" data-title="New sequence">
-            <svg>
-              <use xlinkHref={iconPlus} className="asdcs-icon" />
-            </svg>
-          </button>
-          <button className="asdcs-button-open" data-title="Open sequence">
-            <svg>
-              <use xlinkHref={iconOpen} className="asdcs-icon" />
-            </svg>
-          </button>
-          <button className="asdcs-button-save" data-title="Save checkpoint">
-            <svg>
-              <use xlinkHref="#icon--save" className="asdcs-icon" />
-            </svg>
-          </button>
-          <button className="asdcs-button-validate" data-title="Validate">
-            <svg>
-              <use xlinkHref="#icon--validate" className="asdcs-icon" />
-            </svg>
-          </button>
-          <button className="asdcs-button-download" data-title="Download">
-            <svg>
-              <use xlinkHref="#icon--download" className="asdcs-icon" />
-            </svg>
-          </button>
-          <button className="asdcs-button-upload" data-title="Upload">
-            <svg>
-              <use xlinkHref="#icon--upload" className="asdcs-icon" />
-            </svg>
-          </button>
-        </div>
-        <div className="asdcs-editor-toolbar-toggle">
-          <button className="asdcs-button-design asdcs-button-mode asdcs-button-toggle-left">
-            Design
-          </button>
-          <button className="asdcs-button-json asdcs-button-mode asdcs-button-toggle-center">
-            JSON
-          </button>
-          <button className="asdcs-button-yaml asdcs-button-mode asdcs-button-toggle-right">
-            YAML
-          </button>
-        </div>
-      </div>
-    );
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Render into the DOM.
+     */
+    render() {
+        const demo = this.application.getOptions().demo;
+        const demoCss = demo ? '' : 'asdc-hide';
+
+        return (
+            <div className={`asdcs-editor-toolbar ${demoCss}`}>
+                <div className="asdcs-editor-toolbar-demo">
+                    <button
+                        className="asdcs-button-new"
+                        data-title="New sequence">
+                        <svg>
+                            <use xlinkHref={iconPlus} className="asdcs-icon" />
+                        </svg>
+                    </button>
+                    <button
+                        className="asdcs-button-open"
+                        data-title="Open sequence">
+                        <svg>
+                            <use xlinkHref={iconOpen} className="asdcs-icon" />
+                        </svg>
+                    </button>
+                    <button
+                        className="asdcs-button-save"
+                        data-title="Save checkpoint">
+                        <svg>
+                            <use
+                                xlinkHref="#icon--save"
+                                className="asdcs-icon"
+                            />
+                        </svg>
+                    </button>
+                    <button
+                        className="asdcs-button-validate"
+                        data-title="Validate">
+                        <svg>
+                            <use
+                                xlinkHref="#icon--validate"
+                                className="asdcs-icon"
+                            />
+                        </svg>
+                    </button>
+                    <button
+                        className="asdcs-button-download"
+                        data-title="Download">
+                        <svg>
+                            <use
+                                xlinkHref="#icon--download"
+                                className="asdcs-icon"
+                            />
+                        </svg>
+                    </button>
+                    <button className="asdcs-button-upload" data-title="Upload">
+                        <svg>
+                            <use
+                                xlinkHref="#icon--upload"
+                                className="asdcs-icon"
+                            />
+                        </svg>
+                    </button>
+                </div>
+                <div className="asdcs-editor-toolbar-toggle">
+                    <button className="asdcs-button-design asdcs-button-mode asdcs-button-toggle-left">
+                        Design
+                    </button>
+                    <button className="asdcs-button-json asdcs-button-mode asdcs-button-toggle-center">
+                        JSON
+                    </button>
+                    <button className="asdcs-button-yaml asdcs-button-mode asdcs-button-toggle-right">
+                        YAML
+                    </button>
+                </div>
+            </div>
+        );
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
    * Initialize eventhandlers.
    * @private
    *
@@ -172,9 +192,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoOpen() {
@@ -189,9 +209,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoNew() {
@@ -204,9 +224,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoSave() {
@@ -217,9 +237,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoUpload() {
@@ -241,9 +261,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoDownload() {
@@ -256,9 +276,9 @@ export default class Toolbar extends React.Component {
   }
   */
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
+    /**
    * Demo action.
    *
   _doDemoValidate() {
@@ -270,6 +290,6 @@ export default class Toolbar extends React.Component {
 }
 
 Toolbar.propTypes = {
-  application: PropTypes.object.isRequired,
-  editor: PropTypes.object.isRequired,
+    application: PropTypes.object.isRequired,
+    editor: PropTypes.object.isRequired
 };
index 529ae92..a6cb4ab 100644 (file)
 import React from 'react';
 
 const Export = function Export() {
-  return (
-    <form className="asdcs-export" action="/ossui-svg/services/ossui/svg/export" method="post">
-      <input name="svg" type="hidden" value="" />
-      <input name="css" type="hidden" value="sdc/sequencer/default" />
-      <input name="type" type="hidden" value="PDF" />
-      <input name="height" type="hidden" value="1920" />
-      <input name="width" type="hidden" value="1080" />
-    </form>
-  );
+    return (
+        <form
+            className="asdcs-export"
+            action="/ossui-svg/services/ossui/svg/export"
+            method="post">
+            <input name="svg" type="hidden" value="" />
+            <input name="css" type="hidden" value="sdc/sequencer/default" />
+            <input name="type" type="hidden" value="PDF" />
+            <input name="height" type="hidden" value="1920" />
+            <input name="width" type="hidden" value="1080" />
+        </form>
+    );
 };
 
 export default Export;
index 6ed2d45..5184967 100644 (file)
@@ -24,18 +24,17 @@ import PropTypes from 'prop-types';
  * @constructor
  */
 const Icon = function Icon({ glyph, className }) {
-  return (
-    <svg viewBox="0 0 1000 1000" className={className} >
-      <use xlinkHref={glyph} className="asdcs-icon" />
-    </svg>
-  );
+    return (
+        <svg viewBox="0 0 1000 1000" className={className}>
+            <use xlinkHref={glyph} className="asdcs-icon" />
+        </svg>
+    );
 };
 
 /** Declare properties. */
 Icon.propTypes = {
-  className: PropTypes.string,
-  glyph: PropTypes.string.isRequired,
+    className: PropTypes.string,
+    glyph: PropTypes.string.isRequired
 };
 
 export default Icon;
-
index 817f4f1..7d03b46 100644 (file)
@@ -20,42 +20,35 @@ import React from 'react';
  * Overlay view.
  */
 export default class Overlay extends React.Component {
+    /**
+     * Construct view.
+     * @param props element properties.
+     * @param context react context.
+     */
+    constructor(props, context) {
+        super(props, context);
+        this.state = {
+            visible: false
+        };
+        this.setVisible = this.setVisible.bind(this);
+    }
 
-  /**
-   * Construct view.
-   * @param props element properties.
-   * @param context react context.
-   */
-  constructor(props, context) {
-    super(props, context);
-    this.state = {
-      visible: false,
-    };
-    this.setVisible = this.setVisible.bind(this);
-  }
+    /**
+     * Set visibility.
+     * @param visible true if visible.
+     */
+    setVisible(visible) {
+        this.setState({
+            visible
+        });
+    }
 
-  /**
-   * Set visibility.
-   * @param visible true if visible.
-   */
-  setVisible(visible) {
-    this.setState({
-      visible,
-    });
-  }
-
-  /**
-   * Render view.
-   * @returns {XML}
-   */
-  render() {
-    const display = this.state.visible ? 'block' : 'none';
-    return (
-      <div
-        className="asdcs-overlay"
-        style={{ display }}
-      >
-      </div>
-    );
-  }
+    /**
+     * Render view.
+     * @returns {XML}
+     */
+    render() {
+        const display = this.state.visible ? 'block' : 'none';
+        return <div className="asdcs-overlay" style={{ display }} />;
+    }
 }
index 82e8ada..140b7ef 100644 (file)
@@ -22,73 +22,71 @@ import Common from '../common/Common';
  * Rules governing what a definition can contain.
  */
 export default class Metamodel {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct from JSON definition.
+     * @param json schema definition.
+     */
+    constructor(json) {
+        Common.assertType(json, 'Object');
+        const dfault = require('./templates/default.metamodel.json');
+        this.json = _merge({}, dfault, json);
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct from JSON definition.
-   * @param json schema definition.
-   */
-  constructor(json) {
-    Common.assertType(json, 'Object');
-    const dfault = require('./templates/default.metamodel.json');
-    this.json = _merge({}, dfault, json);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get schema identifier.
-   * @returns ID.
-   */
-  getId() {
-    return this.json.diagram.metadata.id;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Get lifeline constraints.
-   * @returns {*}
-   */
-  getConstraints() {
-    return this.json.diagram.lifelines.constraints;
-  }
+    /**
+     * Get schema identifier.
+     * @returns ID.
+     */
+    getId() {
+        return this.json.diagram.metadata.id;
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Get lifeline metadata by lifeline ID.
-   * @param id sought lifeline.
-   * @returns lifeline if found.
-   */
-  getLifelineById(id) {
-    for (const lifeline of this.json.diagram.lifelines.lifelines) {
-      if (lifeline.id === id) {
-        return lifeline;
-      }
+    /**
+     * Get lifeline constraints.
+     * @returns {*}
+     */
+    getConstraints() {
+        return this.json.diagram.lifelines.constraints;
     }
-    return undefined;
-  }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get lifeline metadata by lifeline ID.
+     * @param id sought lifeline.
+     * @returns lifeline if found.
+     */
+    getLifelineById(id) {
+        for (const lifeline of this.json.diagram.lifelines.lifelines) {
+            if (lifeline.id === id) {
+                return lifeline;
+            }
+        }
+        return undefined;
+    }
 
-  /**
-   * Get original JSON.
-   * @returns JSON.
-   */
-  unwrap() {
-    return this.json;
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Get original JSON.
+     * @returns JSON.
+     */
+    unwrap() {
+        return this.json;
+    }
 
-  /**
-   * Get default schema.
-   * @returns Metamodel default (permissive) Metamodel.
-   */
-  static getDefault() {
-    return new Metamodel({});
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
+    /**
+     * Get default schema.
+     * @returns Metamodel default (permissive) Metamodel.
+     */
+    static getDefault() {
+        return new Metamodel({});
+    }
 }
index 4ecfc0b..40756a8 100644 (file)
@@ -21,67 +21,64 @@ import Metamodel from './Metamodel';
  * A simple lookup for schemas by ID.
  */
 export default class Metamodels {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    /**
+     * Construct metamodels from provided JSON definitions.
+     * @param metamodels JSON metamodel definitions.
+     */
+    constructor(metamodels) {
+        Common.assertType(metamodels, 'Array');
 
-  /**
-   * Construct metamodels from provided JSON definitions.
-   * @param metamodels JSON metamodel definitions.
-   */
-  constructor(metamodels) {
+        this.lookup = {};
 
-    Common.assertType(metamodels, 'Array');
+        // Save each metamodel. It's up to the Metamodel class to make sense of
+        // potentially nonsense metamodel definitions.
 
-    this.lookup = {};
+        for (const json of metamodels) {
+            const metamodel = new Metamodel(json);
+            this.lookup[metamodel.getId()] = metamodel;
+        }
 
-    // Save each metamodel. It's up to the Metamodel class to make sense of
-    // potentially nonsense metamodel definitions.
+        // Set (or override) the default metamodel with the inlined one.
 
-    for (const json of metamodels) {
-      const metamodel = new Metamodel(json);
-      this.lookup[metamodel.getId()] = metamodel;
+        this.lookup.$ = Metamodel.getDefault();
+        Common.assertInstanceOf(this.lookup.$, Metamodel);
     }
 
-    // Set (or override) the default metamodel with the inlined one.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    this.lookup.$ = Metamodel.getDefault();
-    Common.assertInstanceOf(this.lookup.$, Metamodel);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get Metamodel by its @id.
-   * @param id identifier.
-   * @returns Metamodel, or undefined if no matching metamodel found.
-   */
-  getMetamodel(id) {
-    return this.lookup[id];
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get the default (permissive) metamodel.
-   * @returns default Metamodel.
-   */
-  getDefault() {
-    return this.lookup.$;
-  }
+    /**
+     * Get Metamodel by its @id.
+     * @param id identifier.
+     * @returns Metamodel, or undefined if no matching metamodel found.
+     */
+    getMetamodel(id) {
+        return this.lookup[id];
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Get metamodel by its @id, falling back to the default.
-   * @param id identifier.
-   * @returns matching metamodel, or default.
-   */
-  getMetamodelOrDefault(id) {
-    const metamodel = this.getMetamodel(id);
-    if (metamodel) {
-      return metamodel;
+    /**
+     * Get the default (permissive) metamodel.
+     * @returns default Metamodel.
+     */
+    getDefault() {
+        return this.lookup.$;
     }
-    return this.getDefault();
-  }
 
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get metamodel by its @id, falling back to the default.
+     * @param id identifier.
+     * @returns matching metamodel, or default.
+     */
+    getMetamodelOrDefault(id) {
+        const metamodel = this.getMetamodel(id);
+        if (metamodel) {
+            return metamodel;
+        }
+        return this.getDefault();
+    }
 }
index 1e68cd6..3145506 100644 (file)
@@ -24,489 +24,481 @@ import Metamodel from './Metamodel';
  * A wrapper for a model instance.
  */
 export default class Model {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct model from model JSON. JSON is assumed to be in more or less
+     * the correct structure, but it's OK if it's missing IDs.
+     *
+     * @param json initial JSON; will be updated in situ.
+     * @param metamodel Metaobject definition.
+     */
+    constructor(json, metamodel) {
+        if (metamodel) {
+            Common.assertInstanceOf(metamodel, Metamodel);
+        }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+        this.metamodel = metamodel || Metamodel.getDefault();
+        Common.assertInstanceOf(this.metamodel, Metamodel);
 
-  /**
-   * Construct model from model JSON. JSON is assumed to be in more or less
-   * the correct structure, but it's OK if it's missing IDs.
-   *
-   * @param json initial JSON; will be updated in situ.
-   * @param metamodel Metaobject definition.
-   */
-  constructor(json, metamodel) {
+        this.jsonschema = require('./schema/asdc_sequencer_schema.json');
+        this.templates = {
+            defaultModel: require('./templates/default.model.json'),
+            defaultMetamodel: require('./templates/default.metamodel.json')
+        };
 
-    if (metamodel) {
-      Common.assertInstanceOf(metamodel, Metamodel);
-    }
+        this.model = this._preprocess(Common.assertType(json, 'Object'));
+        Common.assertPlainObject(this.model);
 
-    this.metamodel = metamodel || Metamodel.getDefault();
-    Common.assertInstanceOf(this.metamodel, Metamodel);
-
-    this.jsonschema = require('./schema/asdc_sequencer_schema.json');
-    this.templates = {
-      defaultModel: require('./templates/default.model.json'),
-      defaultMetamodel: require('./templates/default.metamodel.json'),
-    };
-
-    this.model = this._preprocess(Common.assertType(json, 'Object'));
-    Common.assertPlainObject(this.model);
-
-    this.renumber();
-
-    this.addLifeline = this.addLifeline.bind(this);
-    this.addMessage = this.addMessage.bind(this);
-    this.renumber = this.renumber.bind(this);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Unwrap to get model object.
-   * @returns {*}
-   */
-  unwrap() {
-    return Common.assertPlainObject(this.model);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get the metamodel which defines valid states for this model.
-   * @returns Metamodel definition.
-   */
-  getMetamodel() {
-    return Common.assertInstanceOf(this.metamodel, Metamodel);
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Find lifeline by its ID.
-   * @param id lifeline ID.
-   * @returns lifeline object, if found.
-   */
-  getLifelineById(id) {
-    for (const lifeline of this.model.diagram.lifelines) {
-      if (lifeline.id === id) {
-        return lifeline;
-      }
-    }
-    return undefined;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get message by ID.
-   * @param id message ID.
-   * @returns message if matched.
-   */
-  getMessageById(id) {
-    Common.assertNotNull(id);
-    const step = this.getStepByMessageId(id);
-    if (step) {
-      return step.message;
+        this.renumber();
+
+        this.addLifeline = this.addLifeline.bind(this);
+        this.addMessage = this.addMessage.bind(this);
+        this.renumber = this.renumber.bind(this);
     }
-    return undefined;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get step by message ID.
-   * @param id step ID.
-   * @returns step if matched.
-   */
-  getStepByMessageId(id) {
-    Common.assertNotNull(id);
-    for (const step of this.model.diagram.steps) {
-      if (step.message && step.message.id === id) {
-        return step;
-      }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Unwrap to get model object.
+     * @returns {*}
+     */
+    unwrap() {
+        return Common.assertPlainObject(this.model);
     }
-    return undefined;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Add message to steps.
-   * @returns {{}}
-   */
-  addMessage(index) {
-    const d = this.model.diagram;
-    const step = {};
-    step.message = {};
-    step.message.id = Model._guid();
-    step.message.name = '[Unnamed Message]';
-    step.message.type = 'request';
-    step.message.from = d.lifelines.length > 0 ? d.lifelines[0].id : -1;
-    step.message.to = d.lifelines.length > 1 ? d.lifelines[1].id : -1;
-    if (index >= 0) {
-      d.steps.splice(index, 0, step);
-    } else {
-      d.steps.push(step);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get the metamodel which defines valid states for this model.
+     * @returns Metamodel definition.
+     */
+    getMetamodel() {
+        return Common.assertInstanceOf(this.metamodel, Metamodel);
     }
-    this.renumber();
-    return step;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Delete message with ID.
-   * @param id to be deleted.
-   */
-  deleteMessageById(id) {
-    Common.assertNotNull(id);
-    const step = this.getStepByMessageId(id);
-    if (step) {
-      const index = this.model.diagram.steps.indexOf(step);
-      if (index !== -1) {
-        this.model.diagram.steps.splice(index, 1);
-      }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Find lifeline by its ID.
+     * @param id lifeline ID.
+     * @returns lifeline object, if found.
+     */
+    getLifelineById(id) {
+        for (const lifeline of this.model.diagram.lifelines) {
+            if (lifeline.id === id) {
+                return lifeline;
+            }
+        }
+        return undefined;
     }
-    this.renumber();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Add lifeline to lifelines.
-   * @param index optional index.
-   * @returns {{}}
-   */
-  addLifeline(index) {
-    const lifeline = {};
-    lifeline.id = Model._guid();
-    lifeline.name = '[Unnamed Lifeline]';
-    if (index >= 0) {
-      this.model.diagram.lifelines.splice(index, 0, lifeline);
-    } else {
-      this.model.diagram.lifelines.push(lifeline);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get message by ID.
+     * @param id message ID.
+     * @returns message if matched.
+     */
+    getMessageById(id) {
+        Common.assertNotNull(id);
+        const step = this.getStepByMessageId(id);
+        if (step) {
+            return step.message;
+        }
+        return undefined;
     }
-    this.renumber();
-    return lifeline;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Delete lifeline with ID.
-   * @param id to be deleted.
-   */
-  deleteLifelineById(id) {
-    Common.assertNotNull(id);
-    this.deleteStepsByLifelineId(id);
-    const lifeline = this.getLifelineById(id);
-    if (lifeline) {
-      const index = this.model.diagram.lifelines.indexOf(lifeline);
-      if (index !== -1) {
-        this.model.diagram.lifelines.splice(index, 1);
-      }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get step by message ID.
+     * @param id step ID.
+     * @returns step if matched.
+     */
+    getStepByMessageId(id) {
+        Common.assertNotNull(id);
+        for (const step of this.model.diagram.steps) {
+            if (step.message && step.message.id === id) {
+                return step;
+            }
+        }
+        return undefined;
     }
-    this.renumber();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Delete all steps corresponding to lifeline.
-   * @param id lifeline ID.
-   */
-  deleteStepsByLifelineId(id) {
-    Common.assertNotNull(id);
-    const steps = this.getStepsByLifelineId(id);
-    for (const step of steps) {
-      this.deleteMessageById(step.message.id);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Add message to steps.
+     * @returns {{}}
+     */
+    addMessage(index) {
+        const d = this.model.diagram;
+        const step = {};
+        step.message = {};
+        step.message.id = Model._guid();
+        step.message.name = '[Unnamed Message]';
+        step.message.type = 'request';
+        step.message.from = d.lifelines.length > 0 ? d.lifelines[0].id : -1;
+        step.message.to = d.lifelines.length > 1 ? d.lifelines[1].id : -1;
+        if (index >= 0) {
+            d.steps.splice(index, 0, step);
+        } else {
+            d.steps.push(step);
+        }
+        this.renumber();
+        return step;
     }
-    this.renumber();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get all steps corresponding to lifeline.
-   * @param id lifeline ID.
-   * @return steps from/to lifeline.
-   */
-  getStepsByLifelineId(id) {
-    Common.assertNotNull(id);
-    const steps = [];
-    for (const step of this.model.diagram.steps) {
-      if (step.message) {
-        if (step.message.from === id || step.message.to === id) {
-          steps.push(step);
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Delete message with ID.
+     * @param id to be deleted.
+     */
+    deleteMessageById(id) {
+        Common.assertNotNull(id);
+        const step = this.getStepByMessageId(id);
+        if (step) {
+            const index = this.model.diagram.steps.indexOf(step);
+            if (index !== -1) {
+                this.model.diagram.steps.splice(index, 1);
+            }
         }
-      }
+        this.renumber();
     }
-    return steps;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Validate model. Disabled, because we removed the jsonschema dependency.
-   * @returns {Array} of validation errors, if any.
-   */
-  validate() {
-    const errors = [];
-    return errors;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Reorder messages.
-   * @param index message index.
-   * @param afterIndex new (after) index.
-   */
-  reorderMessages(index, afterIndex) {
-    Common.assertType(index, 'Number');
-    Common.assertType(afterIndex, 'Number');
-    const steps = this.model.diagram.steps;
-    const element = steps[index];
-    steps.splice(index, 1);
-    steps.splice(afterIndex, 0, element);
-    this.renumber();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Reorder lifelines.
-   * @param index lifeline index.
-   * @param afterIndex new (after) index.
-   */
-  reorderLifelines(index, afterIndex) {
-    Common.assertType(index, 'Number');
-    Common.assertType(afterIndex, 'Number');
-    const lifelines = this.model.diagram.lifelines;
-    const element = lifelines[index];
-    lifelines.splice(index, 1);
-    lifelines.splice(afterIndex, 0, element);
-    this.renumber();
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Renumber lifelines and messages.
-   */
-  renumber() {
-    const modelJSON = this.unwrap();
-    let stepIndex = 1;
-    let lifelineIndex = 1;
-    for (const step of modelJSON.diagram.steps) {
-      if (step.message) {
-        step.message.index = stepIndex++;
-      }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Add lifeline to lifelines.
+     * @param index optional index.
+     * @returns {{}}
+     */
+    addLifeline(index) {
+        const lifeline = {};
+        lifeline.id = Model._guid();
+        lifeline.name = '[Unnamed Lifeline]';
+        if (index >= 0) {
+            this.model.diagram.lifelines.splice(index, 0, lifeline);
+        } else {
+            this.model.diagram.lifelines.push(lifeline);
+        }
+        this.renumber();
+        return lifeline;
     }
-    for (const lifeline of modelJSON.diagram.lifelines) {
-      lifeline.index = lifelineIndex++;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Delete lifeline with ID.
+     * @param id to be deleted.
+     */
+    deleteLifelineById(id) {
+        Common.assertNotNull(id);
+        this.deleteStepsByLifelineId(id);
+        const lifeline = this.getLifelineById(id);
+        if (lifeline) {
+            const index = this.model.diagram.lifelines.indexOf(lifeline);
+            if (index !== -1) {
+                this.model.diagram.lifelines.splice(index, 1);
+            }
+        }
+        this.renumber();
     }
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Build a simple, navigable dataset describing fragments.
-   * @returns {{}}, indexed by (stop) message ID, describing fragments.
-   */
-  analyzeFragments() {
-
-    const fData = {};
-
-    let depth = 0;
-    const modelJSON = this.unwrap();
-    const open = [];
-
-    const getData = function g(stop, fragment) {
-      let data = fData[stop];
-      if (!data) {
-        data = { stop, start: [], fragment };
-        fData[stop] = data;
-      }
-      return data;
-    };
-
-    const fragmentsByStart = {};
-    for (const step of modelJSON.diagram.steps) {
-      if (step.message && step.message.fragment) {
-        const message = step.message;
-        const fragment = message.fragment;
-        if (fragment.start) {
-          fragmentsByStart[fragment.start] = fragment;
-          open.push(message.id);
-          depth++;
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Delete all steps corresponding to lifeline.
+     * @param id lifeline ID.
+     */
+    deleteStepsByLifelineId(id) {
+        Common.assertNotNull(id);
+        const steps = this.getStepsByLifelineId(id);
+        for (const step of steps) {
+            this.deleteMessageById(step.message.id);
         }
-        if (fragment.stop) {
-          if (open.length > 0) {
-            getData(message.id).start.push(open.pop());
-          }
-          depth = Math.max(depth - 1, 0);
+        this.renumber();
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get all steps corresponding to lifeline.
+     * @param id lifeline ID.
+     * @return steps from/to lifeline.
+     */
+    getStepsByLifelineId(id) {
+        Common.assertNotNull(id);
+        const steps = [];
+        for (const step of this.model.diagram.steps) {
+            if (step.message) {
+                if (step.message.from === id || step.message.to === id) {
+                    steps.push(step);
+                }
+            }
         }
-      }
+        return steps;
     }
 
-    if (open.length > 0) {
-      for (const o of open) {
-        getData(o, fragmentsByStart[o]).start.push(o);
-      }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Validate model. Disabled, because we removed the jsonschema dependency.
+     * @returns {Array} of validation errors, if any.
+     */
+    validate() {
+        const errors = [];
+        return errors;
     }
 
-    return fData;
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Reorder messages.
+     * @param index message index.
+     * @param afterIndex new (after) index.
+     */
+    reorderMessages(index, afterIndex) {
+        Common.assertType(index, 'Number');
+        Common.assertType(afterIndex, 'Number');
+        const steps = this.model.diagram.steps;
+        const element = steps[index];
+        steps.splice(index, 1);
+        steps.splice(afterIndex, 0, element);
+        this.renumber();
+    }
 
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Reorder lifelines.
+     * @param index lifeline index.
+     * @param afterIndex new (after) index.
+     */
+    reorderLifelines(index, afterIndex) {
+        Common.assertType(index, 'Number');
+        Common.assertType(afterIndex, 'Number');
+        const lifelines = this.model.diagram.lifelines;
+        const element = lifelines[index];
+        lifelines.splice(index, 1);
+        lifelines.splice(afterIndex, 0, element);
+        this.renumber();
+    }
 
-  /**
-   * Build a simple, navigable dataset describing occurrences.
-   * @returns a map, indexed by lifeline ID, of objects containing {start:[],stop:[],active[]}.
-   * @private
-   */
-  analyzeOccurrences() {
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Renumber lifelines and messages.
+     */
+    renumber() {
+        const modelJSON = this.unwrap();
+        let stepIndex = 1;
+        let lifelineIndex = 1;
+        for (const step of modelJSON.diagram.steps) {
+            if (step.message) {
+                step.message.index = stepIndex++;
+            }
+        }
+        for (const lifeline of modelJSON.diagram.lifelines) {
+            lifeline.index = lifelineIndex++;
+        }
+    }
 
-    const oData = {};
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-    // A few inline functions. They make this method kinda lengthy, but they
-    // reduce clutter in the class and keep it coherent, so it's OK.
+    /**
+     * Build a simple, navigable dataset describing fragments.
+     * @returns {{}}, indexed by (stop) message ID, describing fragments.
+     */
+    analyzeFragments() {
+        const fData = {};
 
-    const getDataByLifelineId = function get(lifelineId) {
-      if (!oData[lifelineId]) {
-        oData[lifelineId] = { active: [], start: {}, stop: {} };
-      }
-      return oData[lifelineId];
-    };
+        let depth = 0;
+        const modelJSON = this.unwrap();
+        const open = [];
 
-    const contains = function contains(array, value) {
-      return (array && (array.indexOf(value) !== -1));
-    };
+        const getData = function g(stop, fragment) {
+            let data = fData[stop];
+            if (!data) {
+                data = { stop, start: [], fragment };
+                fData[stop] = data;
+            }
+            return data;
+        };
+
+        const fragmentsByStart = {};
+        for (const step of modelJSON.diagram.steps) {
+            if (step.message && step.message.fragment) {
+                const message = step.message;
+                const fragment = message.fragment;
+                if (fragment.start) {
+                    fragmentsByStart[fragment.start] = fragment;
+                    open.push(message.id);
+                    depth++;
+                }
+                if (fragment.stop) {
+                    if (open.length > 0) {
+                        getData(message.id).start.push(open.pop());
+                    }
+                    depth = Math.max(depth - 1, 0);
+                }
+            }
+        }
 
-    const process = function process(message, lifelineId) {
-      const oRule = message.occurrences;
-      if (oRule) {
+        if (open.length > 0) {
+            for (const o of open) {
+                getData(o, fragmentsByStart[o]).start.push(o);
+            }
+        }
 
-        const oDataLifeline = getDataByLifelineId(lifelineId);
-        if (oDataLifeline) {
+        return fData;
+    }
 
-          // Record all starts.
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
 
-          if (contains(oRule.start, lifelineId)) {
-            oDataLifeline.active.push(message.id);
-            oDataLifeline.start[message.id] = undefined;
-          }
+    /**
+     * Build a simple, navigable dataset describing occurrences.
+     * @returns a map, indexed by lifeline ID, of objects containing {start:[],stop:[],active[]}.
+     * @private
+     */
+    analyzeOccurrences() {
+        const oData = {};
 
-          // Reconcile with stops.
+        // A few inline functions. They make this method kinda lengthy, but they
+        // reduce clutter in the class and keep it coherent, so it's OK.
 
-          if (contains(oRule.stop, lifelineId)) {
-            const startMessageId = oDataLifeline.active.pop();
-            oDataLifeline.stop[message.id] = startMessageId;
-            if (startMessageId) {
-              oDataLifeline.start[startMessageId] = message.id;
+        const getDataByLifelineId = function get(lifelineId) {
+            if (!oData[lifelineId]) {
+                oData[lifelineId] = { active: [], start: {}, stop: {} };
+            }
+            return oData[lifelineId];
+        };
+
+        const contains = function contains(array, value) {
+            return array && array.indexOf(value) !== -1;
+        };
+
+        const process = function process(message, lifelineId) {
+            const oRule = message.occurrences;
+            if (oRule) {
+                const oDataLifeline = getDataByLifelineId(lifelineId);
+                if (oDataLifeline) {
+                    // Record all starts.
+
+                    if (contains(oRule.start, lifelineId)) {
+                        oDataLifeline.active.push(message.id);
+                        oDataLifeline.start[message.id] = undefined;
+                    }
+
+                    // Reconcile with stops.
+
+                    if (contains(oRule.stop, lifelineId)) {
+                        const startMessageId = oDataLifeline.active.pop();
+                        oDataLifeline.stop[message.id] = startMessageId;
+                        if (startMessageId) {
+                            oDataLifeline.start[startMessageId] = message.id;
+                        }
+                    }
+                }
+            }
+        };
+
+        // Analyze start and end.
+
+        const modelJSON = this.unwrap();
+        for (const step of modelJSON.diagram.steps) {
+            if (step.message) {
+                const message = step.message;
+                if (message.occurrences) {
+                    process(message, message.from);
+                    process(message, message.to);
+                }
             }
-          }
         }
-      }
-    };
-
-    // Analyze start and end.
-
-    const modelJSON = this.unwrap();
-    for (const step of modelJSON.diagram.steps) {
-      if (step.message) {
-        const message = step.message;
-        if (message.occurrences) {
-          process(message, message.from);
-          process(message, message.to);
+
+        // Reset active. (We used it, but it's not actually for us; it's for keeping
+        // track of active occurrences when rendering the diagram.)
+
+        for (const lifelineId of Object.keys(oData)) {
+            oData[lifelineId].active = [];
         }
-      }
-    }
 
-    // Reset active. (We used it, but it's not actually for us; it's for keeping
-    // track of active occurrences when rendering the diagram.)
+        // Reconcile the start and end (message ID) maps for each lifeline,
+        // finding a "stop" for every start. Default to starting and stopping
+        // on the same message, which is the same as no occurrence.
+
+        for (const lifelineId of Object.keys(oData)) {
+            const lifelineData = oData[lifelineId];
+            for (const startId of Object.keys(lifelineData.start)) {
+                const stopId = lifelineData.start[startId];
+                if (!stopId) {
+                    lifelineData.start[startId] = startId;
+                    lifelineData.stop[startId] = startId;
+                }
+            }
+        }
 
-    for (const lifelineId of Object.keys(oData)) {
-      oData[lifelineId].active = [];
+        return oData;
     }
 
-    // Reconcile the start and end (message ID) maps for each lifeline,
-    // finding a "stop" for every start. Default to starting and stopping
-    // on the same message, which is the same as no occurrence.
-
-    for (const lifelineId of Object.keys(oData)) {
-      const lifelineData = oData[lifelineId];
-      for (const startId of Object.keys(lifelineData.start)) {
-        const stopId = lifelineData.start[startId];
-        if (!stopId) {
-          lifelineData.start[startId] = startId;
-          lifelineData.stop[startId] = startId;
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Preprocess model, adding IDs and whatnot.
+     * @param original to be preprocessed.
+     * @returns preprocessed JSON.
+     * @private
+     */
+    _preprocess(original) {
+        const json = _merge({}, this.templates.defaultModel, original);
+        const metamodel = this.metamodel.unwrap();
+        if (!json.diagram.metadata.ref) {
+            if (metamodel.diagram.metadata.id) {
+                json.diagram.metadata.ref = metamodel.diagram.metadata.id;
+            } else {
+                json.diagram.metadata.ref = '$';
+            }
         }
-      }
-    }
 
-    return oData;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Preprocess model, adding IDs and whatnot.
-   * @param original to be preprocessed.
-   * @returns preprocessed JSON.
-   * @private
-   */
-  _preprocess(original) {
-
-    const json = _merge({}, this.templates.defaultModel, original);
-    const metamodel = this.metamodel.unwrap();
-    if (!json.diagram.metadata.ref) {
-      if (metamodel.diagram.metadata.id) {
-        json.diagram.metadata.ref = metamodel.diagram.metadata.id;
-      } else {
-        json.diagram.metadata.ref = '$';
-      }
-    }
+        for (const lifeline of json.diagram.lifelines) {
+            lifeline.id = lifeline.id || lifeline.name;
+        }
 
-    for (const lifeline of json.diagram.lifelines) {
-      lifeline.id = lifeline.id || lifeline.name;
-    }
+        for (const step of json.diagram.steps) {
+            if (step.message) {
+                step.message.id = step.message.id || Model._guid();
+                const occurrences = step.message.occurrences;
+                if (occurrences) {
+                    occurrences.start = occurrences.start || [];
+                    occurrences.stop = occurrences.stop || [];
+                }
+            }
+        }
 
-    for (const step of json.diagram.steps) {
-      if (step.message) {
-        step.message.id = step.message.id || Model._guid();
-        const occurrences = step.message.occurrences;
-        if (occurrences) {
-          occurrences.start = occurrences.start || [];
-          occurrences.stop = occurrences.stop || [];
+        if (!json.diagram.metadata.id || json.diagram.metadata.id === '$') {
+            json.diagram.metadata.id = Model._guid();
         }
-      }
-    }
 
-    if (!json.diagram.metadata.id || json.diagram.metadata.id === '$') {
-      json.diagram.metadata.id = Model._guid();
+        return json;
     }
 
-    return json;
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Create pseudo-UUID.
-   * @returns {string}
-   * @private
-   */
-  static _guid() {
-    function s4() {
-      return Math.floor((1 + Math.random()) * 0x10000)
-        .toString(16)
-        .substring(1);
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Create pseudo-UUID.
+     * @returns {string}
+     * @private
+     */
+    static _guid() {
+        function s4() {
+            return Math.floor((1 + Math.random()) * 0x10000)
+                .toString(16)
+                .substring(1);
+        }
+        return `${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}`;
     }
-    return `${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}`;
-  }
-
 }
index 4130ec7..74707d4 100644 (file)
  * Example scenarios, for development, testing and demos.
  */
 export default class Scenarios {
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Construct scenarios; read model and metamodel templates.
-   */
-  constructor() {
-    this.templates = {
-      model: {
-        ecomp: require('./model/ECOMP.json'),
-        blank: require('./model/BLANK.json'),
-        dimensions: require('./model/DIMENSIONS.json'),
-      },
-      metamodel: {
-        ecomp: require('./metamodel/ECOMP.json'),
-        blank: require('./metamodel/BLANK.json'),
-      },
-    };
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get ECOMP scenario.
-   * @return ECOMP scenario JSON.
-   */
-  getECOMP() {
-    return JSON.parse(JSON.stringify(this.templates.model.ecomp));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get ECOMP scenario metamodel.
-   * @return scenario metamodel JSON.
-   */
-  getECOMPMetamodel() {
-    return JSON.parse(JSON.stringify(this.templates.metamodel.ecomp));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get blank scenario.
-   * @return blank scenario JSON.
-   */
-  getBlank() {
-    return JSON.parse(JSON.stringify(this.templates.model.blank));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get empty scenario metamodel.
-   * @return empty metamodel JSON.
-   */
-  getBlankMetamodel() {
-    return JSON.parse(JSON.stringify(this.templates.metamodel.blank));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get scenario.
-   * @return scenario JSON.
-   */
-  getDimensions() {
-    return JSON.parse(JSON.stringify(this.templates.model.dimensions));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get scenario metamodel.
-   * @return metamodel JSON.
-   */
-  getDimensionsMetamodel() {
-    return JSON.parse(JSON.stringify(this.templates.metamodel.blank));
-  }
-
-  // ///////////////////////////////////////////////////////////////////////////////////////////////
-
-  /**
-   * Get demo metamodels.
-   * @returns {*[]}
-   */
-  getMetamodels() {
-    return [this.getBlankMetamodel(), this.getDimensionsMetamodel(), this.getECOMPMetamodel()];
-  }
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Construct scenarios; read model and metamodel templates.
+     */
+    constructor() {
+        this.templates = {
+            model: {
+                ecomp: require('./model/ECOMP.json'),
+                blank: require('./model/BLANK.json'),
+                dimensions: require('./model/DIMENSIONS.json')
+            },
+            metamodel: {
+                ecomp: require('./metamodel/ECOMP.json'),
+                blank: require('./metamodel/BLANK.json')
+            }
+        };
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get ECOMP scenario.
+     * @return ECOMP scenario JSON.
+     */
+    getECOMP() {
+        return JSON.parse(JSON.stringify(this.templates.model.ecomp));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get ECOMP scenario metamodel.
+     * @return scenario metamodel JSON.
+     */
+    getECOMPMetamodel() {
+        return JSON.parse(JSON.stringify(this.templates.metamodel.ecomp));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get blank scenario.
+     * @return blank scenario JSON.
+     */
+    getBlank() {
+        return JSON.parse(JSON.stringify(this.templates.model.blank));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get empty scenario metamodel.
+     * @return empty metamodel JSON.
+     */
+    getBlankMetamodel() {
+        return JSON.parse(JSON.stringify(this.templates.metamodel.blank));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get scenario.
+     * @return scenario JSON.
+     */
+    getDimensions() {
+        return JSON.parse(JSON.stringify(this.templates.model.dimensions));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get scenario metamodel.
+     * @return metamodel JSON.
+     */
+    getDimensionsMetamodel() {
+        return JSON.parse(JSON.stringify(this.templates.metamodel.blank));
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Get demo metamodels.
+     * @returns {*[]}
+     */
+    getMetamodels() {
+        return [
+            this.getBlankMetamodel(),
+            this.getDimensionsMetamodel(),
+            this.getECOMPMetamodel()
+        ];
+    }
 }
index 4b0f7d2..1c783cb 100644 (file)
@@ -21,15 +21,15 @@ import '../res/ecomp/asdc/sequencer/sequencer-development.scss';
 import '../res/thirdparty/react-select/react-select.min.css';
 
 function renderApplication() {
-  const shell = document.createElement('div');
-  shell.setAttribute('style', 'height:100%;width:100%;margin:0;padding:0');
-  document.body.appendChild(shell);
-  const options = { demo: true };
-  render(<Sequencer options={options} />, shell);
+    const shell = document.createElement('div');
+    shell.setAttribute('style', 'height:100%;width:100%;margin:0;padding:0');
+    document.body.appendChild(shell);
+    const options = { demo: true };
+    render(<Sequencer options={options} />, shell);
 }
 
 if (window.addEventListener) {
-  window.addEventListener('DOMContentLoaded', renderApplication);
+    window.addEventListener('DOMContentLoaded', renderApplication);
 } else {
-  window.attachEvent('onload', renderApplication);
+    window.attachEvent('onload', renderApplication);
 }
index 4f3cc76..043f65b 100644 (file)
@@ -85,14 +85,22 @@ acorn@^4.0.3:
   version "4.0.13"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
 
-acorn@^5.0.0, acorn@^5.2.1:
+acorn@^5.0.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822"
 
-ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
+acorn@^5.4.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.0.tgz#1abb587fbf051f94e3de20e6b26ef910b1828298"
+
+ajv-keywords@^1.1.1:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
 
+ajv-keywords@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be"
+
 ajv@^4.7.0, ajv@^4.9.1:
   version "4.11.8"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
@@ -100,7 +108,7 @@ ajv@^4.7.0, ajv@^4.9.1:
     co "^4.6.0"
     json-stable-stringify "^1.0.1"
 
-ajv@^5.0.0, ajv@^5.1.0:
+ajv@^5.0.0, ajv@^5.1.0, ajv@^5.3.0:
   version "5.5.2"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
   dependencies:
@@ -109,6 +117,14 @@ ajv@^5.0.0, ajv@^5.1.0:
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
 
+ajv@^6.0.1:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.0.tgz#afac295bbaa0152449e522742e4547c1ae9328d2"
+  dependencies:
+    fast-deep-equal "^1.0.0"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.3.0"
+
 align-text@^0.1.1, align-text@^0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
@@ -125,9 +141,9 @@ amdefine@>=0.0.4:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
 
-ansi-escapes@^1.1.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+ansi-escapes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
 
 ansi-green@^0.1.1:
   version "0.1.1"
@@ -151,7 +167,7 @@ ansi-styles@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
 
-ansi-styles@^3.1.0:
+ansi-styles@^3.1.0, ansi-styles@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
   dependencies:
@@ -338,7 +354,7 @@ aws4@^1.2.1, aws4@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
 
-babel-code-frame@^6.26.0:
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
   dependencies:
@@ -1220,7 +1236,7 @@ center-align@^0.1.1:
     align-text "^0.1.3"
     lazy-cache "^1.0.3"
 
-chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
+chalk@^1.1.1, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   dependencies:
@@ -1238,6 +1254,18 @@ chalk@^2.0.0, chalk@^2.3.0:
     escape-string-regexp "^1.0.5"
     supports-color "^4.0.0"
 
+chalk@^2.1.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
+  dependencies:
+    ansi-styles "^3.2.0"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.2.0"
+
+chardet@^0.4.0:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+
 cheerio@^0.19.0:
   version "0.19.0"
   resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
@@ -1310,11 +1338,11 @@ classnames@^2.2.4:
   version "2.2.5"
   resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
 
-cli-cursor@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
   dependencies:
-    restore-cursor "^1.0.1"
+    restore-cursor "^2.0.0"
 
 cli-width@^2.0.0:
   version "2.2.0"
@@ -1450,7 +1478,7 @@ concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
 
-concat-stream@^1.4.6:
+concat-stream@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
   dependencies:
@@ -1576,6 +1604,14 @@ cross-spawn@^3.0.0:
     lru-cache "^4.0.1"
     which "^1.2.9"
 
+cross-spawn@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+  dependencies:
+    lru-cache "^4.0.1"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
 cryptiles@2.x.x:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@@ -1916,16 +1952,6 @@ d3@^4.10.0:
     d3-voronoi "1.1.2"
     d3-zoom "1.7.1"
 
-d@1:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
-  dependencies:
-    es5-ext "^0.10.9"
-
-damerau-levenshtein@^1.0.0:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
-
 dashdash@^1.12.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -1936,7 +1962,7 @@ date-now@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
 
-debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8:
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
   dependencies:
@@ -2093,19 +2119,18 @@ dns-txt@^2.0.2:
   dependencies:
     buffer-indexof "^1.0.0"
 
-doctrine@1.3.x:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.3.0.tgz#13e75682b55518424276f7c173783456ef913d26"
+doctrine@1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
   dependencies:
     esutils "^2.0.2"
     isarray "^1.0.0"
 
-doctrine@^1.2.2:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
+doctrine@^2.0.2, doctrine@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
   dependencies:
     esutils "^2.0.2"
-    isarray "^1.0.0"
 
 dom-serializer@0, dom-serializer@~0.1.0:
   version "0.1.0"
@@ -2232,58 +2257,6 @@ es-to-primitive@^1.1.1:
     is-date-object "^1.0.1"
     is-symbol "^1.0.1"
 
-es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
-  version "0.10.38"
-  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3"
-  dependencies:
-    es6-iterator "~2.0.3"
-    es6-symbol "~3.1.1"
-
-es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
-  dependencies:
-    d "1"
-    es5-ext "^0.10.35"
-    es6-symbol "^3.1.1"
-
-es6-map@^0.1.3:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
-  dependencies:
-    d "1"
-    es5-ext "~0.10.14"
-    es6-iterator "~2.0.1"
-    es6-set "~0.1.5"
-    es6-symbol "~3.1.1"
-    event-emitter "~0.3.5"
-
-es6-set@^0.1.4, es6-set@~0.1.5:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
-  dependencies:
-    d "1"
-    es5-ext "~0.10.14"
-    es6-iterator "~2.0.1"
-    es6-symbol "3.1.1"
-    event-emitter "~0.3.5"
-
-es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
-  dependencies:
-    d "1"
-    es5-ext "~0.10.14"
-
-es6-weak-map@^2.0.1:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
-  dependencies:
-    d "1"
-    es5-ext "^0.10.14"
-    es6-iterator "^2.0.1"
-    es6-symbol "^3.1.1"
-
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -2292,34 +2265,20 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
 
-escope@^3.6.0:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
-  dependencies:
-    es6-map "^0.1.3"
-    es6-weak-map "^2.0.1"
-    esrecurse "^4.1.0"
-    estraverse "^4.1.1"
-
-eslint-config-airbnb-base@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-3.0.1.tgz#b777e01f65e946933442b499fc8518aa251a6530"
-
-eslint-config-airbnb@^9.0.1:
-  version "9.0.1"
-  resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-9.0.1.tgz#6708170d5034b579d52913fe49dee2f7fec7d894"
+eslint-config-prettier@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3"
   dependencies:
-    eslint-config-airbnb-base "^3.0.0"
+    get-stdin "^5.0.1"
 
-eslint-import-resolver-node@^0.2.0:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c"
+eslint-import-resolver-node@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
   dependencies:
-    debug "^2.2.0"
-    object-assign "^4.0.1"
-    resolve "^1.1.6"
+    debug "^2.6.9"
+    resolve "^1.5.0"
 
-eslint-loader@^1.3.0:
+eslint-loader@^1.9.0:
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-1.9.0.tgz#7e1be9feddca328d3dcfaef1ad49d5beffe83a13"
   dependencies:
@@ -2329,43 +2288,45 @@ eslint-loader@^1.3.0:
     object-hash "^1.1.4"
     rimraf "^2.6.1"
 
-eslint-plugin-import@^1.8.0:
-  version "1.16.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz#b2fa07ebcc53504d0f2a4477582ec8bff1871b9f"
+eslint-module-utils@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
+  dependencies:
+    debug "^2.6.8"
+    pkg-dir "^1.0.0"
+
+eslint-plugin-import@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz#26002efbfca5989b7288ac047508bd24f217b169"
   dependencies:
     builtin-modules "^1.1.1"
     contains-path "^0.1.0"
-    debug "^2.2.0"
-    doctrine "1.3.x"
-    es6-map "^0.1.3"
-    es6-set "^0.1.4"
-    eslint-import-resolver-node "^0.2.0"
+    debug "^2.6.8"
+    doctrine "1.5.0"
+    eslint-import-resolver-node "^0.3.1"
+    eslint-module-utils "^2.1.1"
     has "^1.0.1"
-    lodash.cond "^4.3.0"
-    lodash.endswith "^4.0.1"
-    lodash.find "^4.3.0"
-    lodash.findindex "^4.3.0"
+    lodash "^4.17.4"
     minimatch "^3.0.3"
-    object-assign "^4.0.1"
-    pkg-dir "^1.0.0"
-    pkg-up "^1.0.0"
+    read-pkg-up "^2.0.0"
 
-eslint-plugin-jsx-a11y@^1.2.2:
-  version "1.5.5"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-1.5.5.tgz#da284a016c1889e73698180217e2eb988a98bab5"
+eslint-plugin-prettier@^2.6.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
   dependencies:
-    damerau-levenshtein "^1.0.0"
-    jsx-ast-utils "^1.0.0"
-    object-assign "^4.0.1"
+    fast-diff "^1.1.1"
+    jest-docblock "^21.0.0"
 
-eslint-plugin-react@^5.1.1:
-  version "5.2.2"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz#7db068e1f5487f6871e4deef36a381c303eac161"
+eslint-plugin-react@^7.7.0:
+  version "7.7.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160"
   dependencies:
-    doctrine "^1.2.2"
-    jsx-ast-utils "^1.2.1"
+    doctrine "^2.0.2"
+    has "^1.0.1"
+    jsx-ast-utils "^2.0.1"
+    prop-types "^15.6.0"
 
-eslint-scope@~3.7.1:
+eslint-scope@^3.7.1, eslint-scope@~3.7.1:
   version "3.7.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
   dependencies:
@@ -2376,49 +2337,53 @@ eslint-visitor-keys@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
 
-eslint@^2.10.2:
-  version "2.13.1"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11"
+eslint@^4.18.1:
+  version "4.18.1"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.1.tgz#b9138440cb1e98b2f44a0d578c6ecf8eae6150b0"
   dependencies:
-    chalk "^1.1.3"
-    concat-stream "^1.4.6"
-    debug "^2.1.1"
-    doctrine "^1.2.2"
-    es6-map "^0.1.3"
-    escope "^3.6.0"
-    espree "^3.1.6"
-    estraverse "^4.2.0"
+    ajv "^5.3.0"
+    babel-code-frame "^6.22.0"
+    chalk "^2.1.0"
+    concat-stream "^1.6.0"
+    cross-spawn "^5.1.0"
+    debug "^3.1.0"
+    doctrine "^2.1.0"
+    eslint-scope "^3.7.1"
+    eslint-visitor-keys "^1.0.0"
+    espree "^3.5.2"
+    esquery "^1.0.0"
     esutils "^2.0.2"
-    file-entry-cache "^1.1.1"
-    glob "^7.0.3"
-    globals "^9.2.0"
-    ignore "^3.1.2"
+    file-entry-cache "^2.0.0"
+    functional-red-black-tree "^1.0.1"
+    glob "^7.1.2"
+    globals "^11.0.1"
+    ignore "^3.3.3"
     imurmurhash "^0.1.4"
-    inquirer "^0.12.0"
-    is-my-json-valid "^2.10.0"
+    inquirer "^3.0.6"
     is-resolvable "^1.0.0"
-    js-yaml "^3.5.1"
-    json-stable-stringify "^1.0.0"
+    js-yaml "^3.9.1"
+    json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.3.0"
-    lodash "^4.0.0"
-    mkdirp "^0.5.0"
-    optionator "^0.8.1"
-    path-is-absolute "^1.0.0"
-    path-is-inside "^1.0.1"
-    pluralize "^1.2.1"
-    progress "^1.1.8"
-    require-uncached "^1.0.2"
-    shelljs "^0.6.0"
-    strip-json-comments "~1.0.1"
-    table "^3.7.8"
+    lodash "^4.17.4"
+    minimatch "^3.0.2"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.2"
+    pluralize "^7.0.0"
+    progress "^2.0.0"
+    require-uncached "^1.0.3"
+    semver "^5.3.0"
+    strip-ansi "^4.0.0"
+    strip-json-comments "~2.0.1"
+    table "^4.0.1"
     text-table "~0.2.0"
-    user-home "^2.0.0"
 
-espree@^3.1.6:
-  version "3.5.2"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
+espree@^3.5.2:
+  version "3.5.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.3.tgz#931e0af64e7fbbed26b050a29daad1fc64799fa6"
   dependencies:
-    acorn "^5.2.1"
+    acorn "^5.4.0"
     acorn-jsx "^3.0.0"
 
 esprima@^2.6.0:
@@ -2429,6 +2394,12 @@ esprima@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
 
+esquery@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+  dependencies:
+    estraverse "^4.0.0"
+
 esrecurse@^4.1.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
@@ -2436,7 +2407,7 @@ esrecurse@^4.1.0:
     estraverse "^4.1.0"
     object-assign "^4.0.1"
 
-estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
 
@@ -2448,13 +2419,6 @@ etag@~1.8.1:
   version "1.8.1"
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
 
-event-emitter@~0.3.5:
-  version "0.3.5"
-  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
-  dependencies:
-    d "1"
-    es5-ext "~0.10.14"
-
 eventemitter3@1.x.x:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
@@ -2476,10 +2440,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
     md5.js "^1.3.4"
     safe-buffer "^5.1.1"
 
-exit-hook@^1.0.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
-
 expand-brackets@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -2562,6 +2522,14 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
 
+external-editor@^2.0.4:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48"
+  dependencies:
+    chardet "^0.4.0"
+    iconv-lite "^0.4.17"
+    tmp "^0.0.33"
+
 extglob@^0.3.1:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
@@ -2593,6 +2561,10 @@ fast-deep-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
 
+fast-diff@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
+
 fast-json-stable-stringify@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
@@ -2629,12 +2601,11 @@ fbjs@^0.8.16, fbjs@^0.8.9:
     setimmediate "^1.0.5"
     ua-parser-js "^0.7.9"
 
-figures@^1.3.5:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
   dependencies:
     escape-string-regexp "^1.0.5"
-    object-assign "^4.1.0"
 
 file-contents@^0.2.4:
   version "0.2.4"
@@ -2665,9 +2636,9 @@ file-contents@^0.3.1:
     through2 "^2.0.1"
     vinyl "^1.1.1"
 
-file-entry-cache@^1.1.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8"
+file-entry-cache@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
   dependencies:
     flat-cache "^1.2.1"
     object-assign "^4.0.1"
@@ -2754,7 +2725,7 @@ find-up@^1.0.0:
     path-exists "^2.0.0"
     pinkie-promise "^2.0.0"
 
-find-up@^2.1.0:
+find-up@^2.0.0, find-up@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
   dependencies:
@@ -2867,6 +2838,10 @@ function-bind@^1.0.2, function-bind@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
 
+functional-red-black-tree@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+
 gauge@~2.7.3:
   version "2.7.4"
   resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -2904,6 +2879,10 @@ get-stdin@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
 
+get-stdin@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
+
 get-value@^2.0.3, get-value@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -2944,7 +2923,7 @@ glob@^6.0.4:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@~7.1.1:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
   version "7.1.2"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
   dependencies:
@@ -2971,11 +2950,15 @@ global-prefix@^0.1.4:
     is-windows "^0.2.0"
     which "^1.2.12"
 
+globals@^11.0.1:
+  version "11.3.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0"
+
 globals@^11.1.0:
   version "11.1.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.1.0.tgz#632644457f5f0e3ae711807183700ebf2e4633e4"
 
-globals@^9.18.0, globals@^9.2.0:
+globals@^9.18.0:
   version "9.18.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
 
@@ -3061,6 +3044,10 @@ has-flag@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
 
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+
 has-glob@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/has-glob/-/has-glob-0.1.1.tgz#a261c4c2a6c667e0c77b700a7f297c39ef3aa589"
@@ -3259,7 +3246,7 @@ https-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
 
-iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@~0.4.13:
+iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13:
   version "0.4.19"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
 
@@ -3277,7 +3264,7 @@ ieee754@^1.1.4:
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
 
-ignore@^3.1.2:
+ignore@^3.3.3:
   version "3.3.7"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
 
@@ -3333,22 +3320,23 @@ ini@^1.3.4, ini@~1.3.0:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
 
-inquirer@^0.12.0:
-  version "0.12.0"
-  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
+inquirer@^3.0.6:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
   dependencies:
-    ansi-escapes "^1.1.0"
-    ansi-regex "^2.0.0"
-    chalk "^1.0.0"
-    cli-cursor "^1.0.1"
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.0"
+    cli-cursor "^2.1.0"
     cli-width "^2.0.0"
-    figures "^1.3.5"
+    external-editor "^2.0.4"
+    figures "^2.0.0"
     lodash "^4.3.0"
-    readline2 "^1.0.1"
-    run-async "^0.1.0"
-    rx-lite "^3.1.2"
-    string-width "^1.0.1"
-    strip-ansi "^3.0.0"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rx-lite "^4.0.8"
+    rx-lite-aggregates "^4.0.8"
+    string-width "^2.1.0"
+    strip-ansi "^4.0.0"
     through "^2.3.6"
 
 internal-ip@1.2.0:
@@ -3513,7 +3501,7 @@ is-glob@^4.0.0:
   dependencies:
     is-extglob "^2.1.1"
 
-is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
+is-my-json-valid@^2.12.4:
   version "2.17.1"
   resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
   dependencies:
@@ -3574,6 +3562,10 @@ is-primitive@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
 
+is-promise@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
 is-property@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
@@ -3655,6 +3647,10 @@ isstream@~0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
 
+jest-docblock@^21.0.0:
+  version "21.2.0"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
+
 js-base64@^2.1.8, js-base64@^2.1.9:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.2.tgz#1896da010ef8862f385d8887648e9b6dc4a7a2e9"
@@ -3663,7 +3659,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
 
-js-yaml@^3.5.1:
+js-yaml@^3.9.1:
   version "3.10.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
   dependencies:
@@ -3701,7 +3697,11 @@ json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
 
-json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+
+json-stable-stringify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
   dependencies:
@@ -3736,9 +3736,11 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     verror "1.10.0"
 
-jsx-ast-utils@^1.0.0, jsx-ast-utils@^1.2.1:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
+jsx-ast-utils@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f"
+  dependencies:
+    array-includes "^3.0.3"
 
 killable@^1.0.0:
   version "1.0.0"
@@ -3807,6 +3809,15 @@ load-json-file@^1.0.0:
     pinkie-promise "^2.0.0"
     strip-bom "^2.0.0"
 
+load-json-file@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    strip-bom "^3.0.0"
+
 loader-fs-cache@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz#56e0bf08bd9708b26a765b68509840c8dec9fdbc"
@@ -3862,22 +3873,6 @@ lodash.clonedeep@^4.3.2:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
 
-lodash.cond@^4.3.0:
-  version "4.5.2"
-  resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
-
-lodash.endswith@^4.0.1:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09"
-
-lodash.find@^4.3.0:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1"
-
-lodash.findindex@^4.3.0:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106"
-
 lodash.memoize@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@@ -4085,6 +4080,10 @@ mime@^1.4.1, mime@^1.5.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
 
+mimic-fn@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+
 minimalistic-assert@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
@@ -4142,9 +4141,9 @@ multicast-dns@^6.0.1:
     dns-packet "^1.0.1"
     thunky "^0.1.0"
 
-mute-stream@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+mute-stream@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
 
 nan@^2.3.0, nan@^2.3.2:
   version "2.8.0"
@@ -4166,6 +4165,10 @@ nanomatch@^1.2.5:
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
 negotiator@0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
@@ -4394,9 +4397,11 @@ once@^1.3.0, once@^1.3.3:
   dependencies:
     wrappy "1"
 
-onetime@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  dependencies:
+    mimic-fn "^1.0.0"
 
 opn@^5.1.0:
   version "5.2.0"
@@ -4404,7 +4409,7 @@ opn@^5.1.0:
   dependencies:
     is-wsl "^1.1.0"
 
-optionator@^0.8.1:
+optionator@^0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   dependencies:
@@ -4435,7 +4440,7 @@ os-locale@^1.4.0:
   dependencies:
     lcid "^1.0.0"
 
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
 
@@ -4529,7 +4534,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
 
-path-is-inside@^1.0.1:
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
 
@@ -4549,6 +4554,12 @@ path-type@^1.0.0:
     pify "^2.0.0"
     pinkie-promise "^2.0.0"
 
+path-type@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
+  dependencies:
+    pify "^2.0.0"
+
 path@^0.12.7:
   version "0.12.7"
   resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f"
@@ -4604,15 +4615,9 @@ pkg-dir@^2.0.0:
   dependencies:
     find-up "^2.1.0"
 
-pkg-up@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26"
-  dependencies:
-    find-up "^1.0.0"
-
-pluralize@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
+pluralize@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
 
 portfinder@^1.0.9:
   version "1.0.13"
@@ -4884,6 +4889,10 @@ preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
 
+prettier@^1.10.2:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.0.tgz#c024f70cab158c993f50fc0c25ffe738cb8b0f85"
+
 private@^0.1.6, private@^0.1.7:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -4896,9 +4905,9 @@ process@^0.11.1, process@^0.11.10:
   version "0.11.10"
   resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
 
-progress@^1.1.8:
-  version "1.1.8"
-  resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
+progress@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
 
 promise@^7.1.1:
   version "7.3.1"
@@ -5100,6 +5109,13 @@ read-pkg-up@^1.0.1:
     find-up "^1.0.0"
     read-pkg "^1.0.0"
 
+read-pkg-up@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
+  dependencies:
+    find-up "^2.0.0"
+    read-pkg "^2.0.0"
+
 read-pkg@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
@@ -5108,6 +5124,14 @@ read-pkg@^1.0.0:
     normalize-package-data "^2.3.2"
     path-type "^1.0.0"
 
+read-pkg@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
+  dependencies:
+    load-json-file "^2.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^2.0.0"
+
 readable-stream@1.1:
   version "1.1.13"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
@@ -5138,14 +5162,6 @@ readdirp@^2.0.0:
     readable-stream "^2.0.2"
     set-immediate-shim "^1.0.1"
 
-readline2@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
-  dependencies:
-    code-point-at "^1.0.0"
-    is-fullwidth-code-point "^1.0.0"
-    mute-stream "0.0.5"
-
 redent@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -5358,7 +5374,7 @@ require-package-name@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
 
-require-uncached@^1.0.2:
+require-uncached@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
   dependencies:
@@ -5394,18 +5410,18 @@ resolve-url@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
 
-resolve@^1.1.6:
+resolve@^1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
   dependencies:
     path-parse "^1.0.5"
 
-restore-cursor@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
   dependencies:
-    exit-hook "^1.0.0"
-    onetime "^1.0.0"
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
 
 right-align@^0.1.1:
   version "0.1.3"
@@ -5426,19 +5442,25 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^2.0.0"
     inherits "^2.0.1"
 
-run-async@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+run-async@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
   dependencies:
-    once "^1.3.0"
+    is-promise "^2.1.0"
 
 rw@1:
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
 
-rx-lite@^3.1.2:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+rx-lite-aggregates@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
+  dependencies:
+    rx-lite "*"
+
+rx-lite@*, rx-lite@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
 
 safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.1"
@@ -5597,11 +5619,17 @@ shallow-clone@^0.1.2:
     lazy-cache "^0.2.3"
     mixin-object "^2.0.1"
 
-shelljs@^0.6.0:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
 
-signal-exit@^3.0.0:
+signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
@@ -5609,9 +5637,11 @@ slash@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
 
-slice-ansi@0.0.4:
-  version "0.0.4"
-  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+slice-ansi@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
 
 snapdragon-node@^2.0.1:
   version "2.1.1"
@@ -5829,7 +5859,7 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
 
-string-width@^2.0.0:
+string-width@^2.1.0, string-width@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
   dependencies:
@@ -5879,16 +5909,16 @@ strip-bom@^2.0.0:
   dependencies:
     is-utf8 "^0.2.0"
 
+strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
 strip-indent@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
   dependencies:
     get-stdin "^4.0.1"
 
-strip-json-comments@~1.0.1:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
-
 strip-json-comments@~2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
@@ -5926,6 +5956,12 @@ supports-color@^5.1.0:
   dependencies:
     has-flag "^2.0.0"
 
+supports-color@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
+  dependencies:
+    has-flag "^3.0.0"
+
 svg-sprite-loader@0.0.19:
   version "0.0.19"
   resolved "https://registry.yarnpkg.com/svg-sprite-loader/-/svg-sprite-loader-0.0.19.tgz#769a83009e34a1111b08efc84ae6df3038564542"
@@ -5952,16 +5988,16 @@ symbol-observable@^1.0.2, symbol-observable@^1.0.3:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32"
 
-table@^3.7.8:
-  version "3.8.3"
-  resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
+table@^4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
   dependencies:
-    ajv "^4.7.0"
-    ajv-keywords "^1.0.0"
-    chalk "^1.1.1"
-    lodash "^4.0.0"
-    slice-ansi "0.0.4"
-    string-width "^2.0.0"
+    ajv "^6.0.1"
+    ajv-keywords "^3.0.0"
+    chalk "^2.1.0"
+    lodash "^4.17.4"
+    slice-ansi "1.0.0"
+    string-width "^2.1.1"
 
 tapable@^0.2.7, tapable@~0.2.5:
   version "0.2.8"
@@ -6017,6 +6053,12 @@ timers-browserify@^2.0.4:
   dependencies:
     setimmediate "^1.0.4"
 
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  dependencies:
+    os-tmpdir "~1.0.2"
+
 to-arraybuffer@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@@ -6214,12 +6256,6 @@ use@^2.0.0:
     isobject "^3.0.0"
     lazy-cache "^2.0.2"
 
-user-home@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
-  dependencies:
-    os-homedir "^1.0.0"
-
 util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
index 2ebd851..5bc1423 100644 (file)
@@ -1,5 +1,15 @@
 {
   "parser": "babel-eslint",
+  "parserOptions": {
+    "ecmaVersion": 6,
+    "sourceType": "module",
+    "ecmaFeatures": {
+      "jsx": true,
+      "classes": true,
+      "modules": true,
+      "experimentalDecorators": true
+    }
+  },
   "env": {
     "es6": true,
     "jquery": true,
   },
   "plugins": [
     "react",
-    "import"
+    "import",
+    "prettier"
+  ],
+  "extends": [
+    "prettier"
   ],
-  "ecmaFeatures": {
-    "jsx": true,
-    "classes": true,
-    "modules": true,
-    "experimentalDecorators": true
-  },
   "globals": {
     "Event": true,
     "window": true,
     "describe": true
   },
   "rules": {
+    "prettier/prettier": ["error", {
+      "singleQuote": true,
+      "jsxBracketSameLine": true,
+      "tabWidth": 4
+    }],
     "linebreak-style": 0,
     "no-unused-vars": 2,
     "no-bitwise": 0,
     "no-eq-null": 2,
     "eqeqeq": 2,
-    "wrap-iife": [
-      2,
-      "any"
-    ],
     "no-unused-expressions": 2,
-    "indent": [
-      1,
-      "tab",
-      {
-        "SwitchCase": 1
-      }
-    ],
     "no-use-before-define": 2,
     "new-cap": [
       2,
       "single",
       "avoid-escape"
     ],
-    "jsx-quotes": [
-      2,
-      "prefer-single"
-    ],
     "no-plusplus": 0,
     "no-cond-assign": [
       2,
       "except-parens"
     ],
-    "comma-style": [
-      2,
-      "last"
-    ],
     "no-invalid-this": 0,
     "dot-notation": 0,
-    "max-len": [
-      1,
-      200
-    ],
     "camelcase": [
       2,
       {
       }
     ],
     "curly": 2,
-    "brace-style": 0,
     "semi": [
       2,
       "always"
     ],
-    "space-in-brackets": [
-      0,
-      "never"
-    ],
-    "space-infix-ops": 2,
     "import/default": 0,
     "import/no-unresolved": 0,
     "import/no-named-as-default": 2,
     "react/display-name": 0,
     "react/forbid-prop-types": 0,
     "react/jsx-boolean-value": 0,
-    "react/jsx-closing-bracket-location": [
-      1,
-      {
-        "nonEmpty": "after-props",
-        "selfClosing": "after-props"
-      }
-    ],
-    "react/jsx-curly-spacing": 0,
-    "react/jsx-indent-props": [
-      1,
-      "tab"
-    ],
-    "react/jsx-max-props-per-line": 0,
     "react/jsx-no-duplicate-props": 1,
     "react/jsx-no-literals": 0,
     "react/jsx-no-undef": 1,
     "react/no-unknown-property": 1,
     "react/prop-types": 0,
     "react/react-in-jsx-scope": 1,
-    "react/require-extension": 1,
     "react/self-closing-comp": 1,
     "react/sort-comp": 0,
-    "react/wrap-multilines": 1
   }
 }
diff --git a/openecomp-ui/.prettierrc b/openecomp-ui/.prettierrc
new file mode 100644 (file)
index 0000000..0a7b3ae
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "singleQuote": true,
+  "jsxBracketSameLine": true,
+  "tabWidth": 4
+}
index ecc28f7..70c86cc 100644 (file)
 {
-  "name": "dox-ui",
-  "version": "1.0.0",
-  "description": "",
-  "author": "ONAP",
-  "license": "SEE LICENSE IN LICENSE",
-  "scripts": {
-    "start": "gulp dev && webpack-dev-server --progress",
-    "build": "gulp build",
-    "css-usage": "gulp css-usage",
-    "static-keys-bundle": "gulp static-keys-bundle",
-    "check-keys-against-bundles": "gulp static-keys-bundle-with-report",
-    "test": "jest",
-    "test-failedTestReport": "jest --json | node test-utils/failedTestReport.js",
-    "test-dev": "jest --watch",
-    "test-coverage": "jest --coverage && start ./coverage/lcov-report/index.html",
-    "test-build": "jest --coverage",
-    "storybook": "start-storybook -p 9090 -c .storybook -s .storybook/fonts",
-    "storyshots": "jest storyshots.test.js",
-    "build-storybook": "build-storybook -c .storybook -o .storybook-dist && gulp copy-storybook-fonts"
-  },
-  "dependencies": {
-    "attr-accept": "^1.1.0",
-    "axios": "^0.16.2",
-    "classnames": "^2.2.5",
-    "core-js": "^2.4.0",
-    "d3": "^4.10.0",
-    "dox-sequence-diagram-ui": "file:../dox-sequence-diagram-ui",
-    "intl": "^1.0.1",
-    "intl-format-cache": "^2.0.5",
-    "intl-messageformat": "^1.2.0",
-    "intl-relativeformat": "^1.2.0",
-    "lodash": "^4.13.1",
-    "md5": "^2.1.0",
-    "prop-types": "^15.6.0",
-    "randomstring": "^1.1.5",
-    "react": "^15.6.2",
-    "react-dnd": "^2.5.4",
-    "react-dnd-html5-backend": "^2.5.4",
-    "react-dom": "^15.6.2",
-    "react-redux": "^5.0.6",
-    "react-select": "1.2.1",
-    "redux": "^3.7.2",
-    "react-bootstrap": "^0.32.1",
-    "react-click-outside": "^2.3.1",
-    "react-datepicker": "^0.48.0",
-    "react-dropzone": "4.2.3",
-    "react-input-autosize": "^2.2.0",
-    "react-show-more": "^1.1.1",
-    "react-sortable": "^1.2.0",
-    "sdc-ui": "1.6.24",
-    "uuid-js": "^0.7.5",
-    "validator": "^4.3.0"
-  },
-  "devDependencies": {
-    "@kadira/storybook": "^2.35.3",
-    "@kadira/storybook-addon-knobs": "^1.7.1",
-    "@kadira/storybook-addon-options": "^1.0.2",
-    "babel-core": "^6.24.0",
-    "babel-eslint": "^7.2.1",
-    "babel-jest": "^22.1.0",
-    "babel-loader": "^7.0.0-beta.1",
-    "babel-plugin-transform-class-properties": "^6.10.2",
-    "babel-plugin-transform-decorators-legacy": "^1.3.4",
-    "babel-plugin-transform-object-rest-spread": "^6.8.0",
-    "babel-plugin-transform-runtime": "^6.22.0",
-    "babel-preset-env": "^1.6.1",
-    "babel-preset-react": "^6.23.0",
-    "css-loader": "^0.23.1",
-    "deep-freeze": "0.0.1",
-    "del": "^3.0.0",
-    "enzyme": "^2.7.1",
-    "eslint": "^2.13.1",
-    "eslint-loader": "^1.3.0",
-    "eslint-plugin-import": "^0.8.1",
-    "eslint-plugin-react": "^3.14.0",
-    "express": "^4.13.3",
-    "file-loader": "^0.8.5",
-    "gulp": "^3.9.1",
-    "gulp-clean": "^0.3.1",
-    "gulp-css-usage": "^2.0.0",
-    "gulp-rename": "^1.2.2",
-    "gulp-replace": "^0.5.4",
-    "gulp-sass": "^3.1.0",
-    "gulp-tap": "^1.0.1",
-    "gulp-zip": "^4.1.0",
-    "html-loader": "^0.4.3",
-    "http-proxy-middleware": "^0.17.4",
-    "ignore-loader": "^0.1.1",
-    "jasmine-core": "^2.5.2",
-    "jest": "^21.2.1",
-    "jshint": "^2.9.4",
-    "json-loader": "^0.5.4",
-    "jsx-loader": "^0.13.2",
-    "mkdirp": "^0.5.1",
-    "moment": "^2.18.1",
-    "node-sass": "^4.7.2",
-    "node-watch": "^0.3.5",
-    "prompt": "^0.2.14",
-    "react-addons-test-utils": "~15.3.2",
-    "react-hot-loader": "^3.1.3",
-    "rosie": "^1.6.0",
-    "run-sequence": "^2.2.1",
-    "sass-loader": "^6.0.6",
-    "source-map-loader": "^0.1.5",
-    "storyshots": "^3.2.2",
-    "style-loader": "^0.13.0",
-    "svg-sprite-loader": "^0.1.1",
-    "url-loader": "^0.5.7",
-    "webpack": "^2.2.1",
-    "webpack-dev-server": "^2.4.2"
-  },
-  "engines": {
-    "node": ">=8.0.0",
-    "npm": ">=5.0.0",
-    "yarn": "^1.3.2"
-  },
-  "jest": {
-    "moduleNameMapper": {
-      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test-utils/fileMock.js",
-      "\\.(css|scss)$": "<rootDir>/test-utils/styleMock.js",
-      "^nfvo-utils/RestAPIUtil.js$": "<rootDir>/test-utils/MockRest.js",
-      "^sdc-ui/lib/react/SVGIcon.js$": "<rootDir>/test-utils/MockSVGIcon.js",
-      "^react-show-more$": "<rootDir>/test-utils/ShowMore.js",
-      "^nfvo-utils(.*)$": "<rootDir>/src/nfvo-utils$1",
-      "^nfvo-components(.*)$": "<rootDir>/src/nfvo-components$1",
-      "^sdc-app(.*)$": "<rootDir>/src/sdc-app$1",
-      "^test-utils(.*)$": "<rootDir>/test-utils$1",
-      "^i18nJson$": "<rootDir>/src/nfvo-utils/i18n/en.json",
-      "^src(.*)$": "<rootDir>/src$1"
+    "name": "dox-ui",
+    "version": "1.0.0",
+    "description": "",
+    "author": "ONAP",
+    "license": "SEE LICENSE IN LICENSE",
+    "scripts": {
+        "start": "gulp dev && webpack-dev-server --progress",
+        "build": "gulp build",
+        "css-usage": "gulp css-usage",
+        "static-keys-bundle": "gulp static-keys-bundle",
+        "check-keys-against-bundles": "gulp static-keys-bundle-with-report",
+        "test": "jest",
+        "test-failedTestReport": "jest --json | node test-utils/failedTestReport.js",
+        "test-dev": "jest --watch",
+        "test-coverage": "jest --coverage && start ./coverage/lcov-report/index.html",
+        "test-build": "jest --coverage",
+        "storybook": "start-storybook -p 9090 -c .storybook -s .storybook/fonts",
+        "storyshots": "jest storyshots.test.js",
+        "build-storybook": "build-storybook -c .storybook -o .storybook-dist && gulp copy-storybook-fonts",
+        "lint-fix": "eslint --fix  --ext .js --ext .jsx src"
     },
-    "globals": {
-      "DEBUG": false
+    "dependencies": {
+        "attr-accept": "^1.1.0",
+        "axios": "^0.16.2",
+        "classnames": "^2.2.5",
+        "core-js": "^2.4.0",
+        "d3": "^4.10.0",
+        "dox-sequence-diagram-ui": "file:../dox-sequence-diagram-ui",
+        "intl": "^1.0.1",
+        "intl-format-cache": "^2.0.5",
+        "intl-messageformat": "^1.2.0",
+        "intl-relativeformat": "^1.2.0",
+        "lodash": "^4.13.1",
+        "md5": "^2.1.0",
+        "prop-types": "^15.6.0",
+        "randomstring": "^1.1.5",
+        "react": "^15.6.2",
+        "react-bootstrap": "^0.32.1",
+        "react-click-outside": "^2.3.1",
+        "react-datepicker": "^0.48.0",
+        "react-dnd": "^2.5.4",
+        "react-dnd-html5-backend": "^2.5.4",
+        "react-dom": "^15.6.2",
+        "react-dropzone": "4.2.3",
+        "react-input-autosize": "^2.2.0",
+        "react-redux": "^5.0.6",
+        "react-select": "1.2.1",
+        "react-show-more": "^1.1.1",
+        "react-sortable": "^1.2.0",
+        "redux": "^3.7.2",
+        "sdc-ui": "1.6.24",
+        "uuid-js": "^0.7.5",
+        "validator": "^4.3.0"
     },
-    "setupFiles": [
-      "<rootDir>/test-utils/test-env-setup.js"
-    ],
-    "setupTestFrameworkScriptFile": "<rootDir>/test-utils/test-setup.js",
-    "testPathIgnorePatterns": [
-      "<rootDir>/node_modules/",
-      "<rootDir>/test/nfvo-components/storyshots.test.js"
-    ],
-    "collectCoverageFrom": [
-      "src/**/*.{js,jsx}"
-    ],
-    "coveragePathIgnorePatterns": [
-      "/node_modules/",
-      "(.)*.stories.js"
-    ],
-    "coverageReporters": [
-      "lcov"
-    ]
-  }
+    "devDependencies": {
+        "@kadira/storybook": "^2.35.3",
+        "@kadira/storybook-addon-knobs": "^1.7.1",
+        "@kadira/storybook-addon-options": "^1.0.2",
+        "babel-core": "^6.24.0",
+        "babel-eslint": "^8.2.1",
+        "babel-jest": "^22.1.0",
+        "babel-loader": "^7.0.0-beta.1",
+        "babel-plugin-transform-class-properties": "^6.10.2",
+        "babel-plugin-transform-decorators-legacy": "^1.3.4",
+        "babel-plugin-transform-object-rest-spread": "^6.8.0",
+        "babel-plugin-transform-runtime": "^6.22.0",
+        "babel-preset-env": "^1.6.1",
+        "babel-preset-react": "^6.23.0",
+        "css-loader": "^0.23.1",
+        "deep-freeze": "0.0.1",
+        "del": "^3.0.0",
+        "enzyme": "^2.7.1",
+        "eslint": "^4.18.1",
+        "eslint-config-prettier": "^2.9.0",
+        "eslint-loader": "^2.0.0",
+        "eslint-plugin-import": "^2.9.0",
+        "eslint-plugin-prettier": "^2.6.0",
+        "eslint-plugin-react": "^7.7.0",
+        "express": "^4.13.3",
+        "file-loader": "^0.8.5",
+        "gulp": "^3.9.1",
+        "gulp-clean": "^0.3.1",
+        "gulp-css-usage": "^2.0.0",
+        "gulp-rename": "^1.2.2",
+        "gulp-replace": "^0.5.4",
+        "gulp-sass": "^3.1.0",
+        "gulp-tap": "^1.0.1",
+        "gulp-zip": "^4.1.0",
+        "html-loader": "^0.4.3",
+        "http-proxy-middleware": "^0.17.4",
+        "ignore-loader": "^0.1.1",
+        "jasmine-core": "^2.5.2",
+        "jest": "^21.2.1",
+        "jshint": "^2.9.4",
+        "json-loader": "^0.5.4",
+        "jsx-loader": "^0.13.2",
+        "mkdirp": "^0.5.1",
+        "moment": "^2.18.1",
+        "node-sass": "^4.7.2",
+        "node-watch": "^0.3.5",
+        "prettier": "^1.10.2",
+        "prompt": "^0.2.14",
+        "react-addons-test-utils": "~15.3.2",
+        "react-hot-loader": "^3.1.3",
+        "rosie": "^1.6.0",
+        "run-sequence": "^2.2.1",
+        "sass-loader": "^6.0.6",
+        "source-map-loader": "^0.1.5",
+        "storyshots": "^3.2.2",
+        "style-loader": "^0.13.0",
+        "svg-sprite-loader": "^0.1.1",
+        "url-loader": "^0.5.7",
+        "webpack": "^2.2.1",
+        "webpack-dev-server": "^2.4.2"
+    },
+    "engines": {
+        "node": ">=8.0.0",
+        "npm": ">=5.0.0",
+        "yarn": "^1.3.2"
+    },
+    "jest": {
+        "moduleNameMapper": {
+            "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test-utils/fileMock.js",
+            "\\.(css|scss)$": "<rootDir>/test-utils/styleMock.js",
+            "^nfvo-utils/RestAPIUtil.js$": "<rootDir>/test-utils/MockRest.js",
+            "^sdc-ui/lib/react/SVGIcon.js$": "<rootDir>/test-utils/MockSVGIcon.js",
+            "^react-show-more$": "<rootDir>/test-utils/ShowMore.js",
+            "^nfvo-utils(.*)$": "<rootDir>/src/nfvo-utils$1",
+            "^nfvo-components(.*)$": "<rootDir>/src/nfvo-components$1",
+            "^sdc-app(.*)$": "<rootDir>/src/sdc-app$1",
+            "^test-utils(.*)$": "<rootDir>/test-utils$1",
+            "^i18nJson$": "<rootDir>/src/nfvo-utils/i18n/en.json",
+            "^src(.*)$": "<rootDir>/src$1"
+        },
+        "globals": {
+            "DEBUG": false
+        },
+        "setupFiles": [
+            "<rootDir>/test-utils/test-env-setup.js"
+        ],
+        "setupTestFrameworkScriptFile": "<rootDir>/test-utils/test-setup.js",
+        "testPathIgnorePatterns": [
+            "<rootDir>/node_modules/",
+            "<rootDir>/test/nfvo-components/storyshots.test.js"
+        ],
+        "collectCoverageFrom": [
+            "src/**/*.{js,jsx}"
+        ],
+        "coveragePathIgnorePatterns": [
+            "/node_modules/",
+            "(.)*.stories.js"
+        ],
+        "coverageReporters": [
+            "lcov"
+        ]
+    }
 }
index c15cd1d..56382d6 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import ListGroupItem from 'react-bootstrap/lib/ListGroupItem.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
-import {Collapse} from 'react-bootstrap';
+import { Collapse } from 'react-bootstrap';
 /**
  * parsing and showing the following Java Response object
  *
@@ -42,121 +42,151 @@ import {Collapse} from 'react-bootstrap';
     }
  */
 class SubmitErrorResponse extends Component {
+    render() {
+        let {
+            validationResponse: {
+                vspErrors,
+                licensingDataErrors,
+                questionnaireValidationResult,
+                uploadDataErrors
+            }
+        } = this.props;
+        return (
+            <div className="submit-error-response-view">
+                {vspErrors && this.renderVspErrors(vspErrors)}
+                {licensingDataErrors &&
+                    this.renderVspErrors(licensingDataErrors)}
+                {questionnaireValidationResult &&
+                    this.renderComponentsErrors(questionnaireValidationResult)}
+                {uploadDataErrors &&
+                    this.renderUploadDataErrors(uploadDataErrors)}
+            </div>
+        );
+    }
 
+    renderVspErrors(errors) {
+        return (
+            <ErrorBlock errorType={i18n('VSP Errors')}>
+                <div>
+                    {errors.length &&
+                        errors.map((error, i) => {
+                            return (
+                                <ErrorMessage key={i} error={error.message} />
+                            );
+                        })}
+                </div>
+            </ErrorBlock>
+        );
+    }
 
-       render() {
-               let {validationResponse : {vspErrors, licensingDataErrors, questionnaireValidationResult, uploadDataErrors}} = this.props;
-               return (
-                       <div className='submit-error-response-view'>
-                               {vspErrors && this.renderVspErrors(vspErrors)}
-                               {licensingDataErrors && this.renderVspErrors(licensingDataErrors)}
-                               {questionnaireValidationResult && this.renderComponentsErrors(questionnaireValidationResult)}
-                               {uploadDataErrors && this.renderUploadDataErrors(uploadDataErrors)}
-                       </div>
-               );
-       }
-
-       renderVspErrors(errors) {
-               return (
-                       <ErrorBlock errorType={i18n('VSP Errors')}>
-                               <div>
-                                       {errors.length && errors.map((error, i) => {return (<ErrorMessage key={i} error={error.message}/>);})}
-                               </div>
-                       </ErrorBlock>
-               );
-       }
-
-
-       renderComponentsErrors(errors) {
-               return (
-                       <ErrorBlock errorType={i18n('Components Errors')}>
-                               <div>
-                                       {errors.validationData.length && errors.validationData.map((item, i) =>{ return (<ComponentError key={i} item={item}/>);})}
-                               </div>
-                       </ErrorBlock>
-               );
-       }
+    renderComponentsErrors(errors) {
+        return (
+            <ErrorBlock errorType={i18n('Components Errors')}>
+                <div>
+                    {errors.validationData.length &&
+                        errors.validationData.map((item, i) => {
+                            return <ComponentError key={i} item={item} />;
+                        })}
+                </div>
+            </ErrorBlock>
+        );
+    }
 
-       renderUploadDataErrors(uploadDataErrors) {
-               return (
-                       <ErrorBlock errorType={i18n('Upload Data Errors')}>
-                               <div>
-                                       <UploadErrorList items={uploadDataErrors}/>
-                               </div>
-                       </ErrorBlock>
-               );
-       }
+    renderUploadDataErrors(uploadDataErrors) {
+        return (
+            <ErrorBlock errorType={i18n('Upload Data Errors')}>
+                <div>
+                    <UploadErrorList items={uploadDataErrors} />
+                </div>
+            </ErrorBlock>
+        );
+    }
 }
 
-
-const ComponentError = ({item}) => {
-       return (
-               <div>
-                       <div className='component-name-header'>{item.entityName}</div>
-                       {item.errors.map((error, i) => {return(<ErrorMessage key={i} error={error}/>);})}
-               </div>
-       );
+const ComponentError = ({ item }) => {
+    return (
+        <div>
+            <div className="component-name-header">{item.entityName}</div>
+            {item.errors.map((error, i) => {
+                return <ErrorMessage key={i} error={error} />;
+            })}
+        </div>
+    );
 };
 
 function* entries(obj) {
-       for (let key of Object.keys(obj)) {
-               yield {header: key, list: obj[key]};
-       }
+    for (let key of Object.keys(obj)) {
+        yield { header: key, list: obj[key] };
+    }
 }
 
-const UploadErrorList = ({items}) => {
-       let generator = entries(items);
-
-       let errors = [];
-       for (let item of generator) {errors.push(
-               <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>
-       );}
+const UploadErrorList = ({ items }) => {
+    let generator = entries(items);
+
+    let errors = [];
+    for (let item of generator) {
+        errors.push(
+            <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>
+        );
+    }
 
-       return (
-               <div>
-                       {errors}
-               </div>
-       );
+    return <div>{errors}</div>;
 };
 
 class ErrorBlock extends React.Component {
-       state = {
-               collapsed: false
-       };
-
-       render() {
-               let {errorType, children} = this.props;
-               return (
-                       <div className='error-block'>
-                               <ErrorHeader collapsed={this.state.collapsed} onClick={()=>{this.setState({collapsed: !this.state.collapsed});}} errorType={errorType}/>
-                               <Collapse in={this.state.collapsed}>
-                                       {children}
-                               </Collapse>
-                       </div>
-               );
-       }
+    state = {
+        collapsed: false
+    };
+
+    render() {
+        let { errorType, children } = this.props;
+        return (
+            <div className="error-block">
+                <ErrorHeader
+                    collapsed={this.state.collapsed}
+                    onClick={() => {
+                        this.setState({ collapsed: !this.state.collapsed });
+                    }}
+                    errorType={errorType}
+                />
+                <Collapse in={this.state.collapsed}>{children}</Collapse>
+            </div>
+        );
+    }
 }
 
-const ErrorHeader = ({errorType, collapsed, onClick}) => {
-       return(
-               <div onClick={onClick} className='error-block-header'>
-                       <SVGIcon iconClassName={collapsed ? '' : 'collapse-right' } name='chevronDown' label={errorType} labelPosition='right'/>
-               </div>
-       );
+const ErrorHeader = ({ errorType, collapsed, onClick }) => {
+    return (
+        <div onClick={onClick} className="error-block-header">
+            <SVGIcon
+                iconClassName={collapsed ? '' : 'collapse-right'}
+                name="chevronDown"
+                label={errorType}
+                labelPosition="right"
+            />
+        </div>
+    );
 };
 
-const ErrorMessage = ({error, warning}) => {
-       return (
-               <ListGroupItem className='error-code-list-item'>
-                       <SVGIcon
-                               name={warning ? 'exclamationTriangleLine' : 'error'}
-                               color={warning ? 'warning' : 'negative'} />
-                       <span className='icon-label'>{error}</span>
-               </ListGroupItem>
-       );
+const ErrorMessage = ({ error, warning }) => {
+    return (
+        <ListGroupItem className="error-code-list-item">
+            <SVGIcon
+                name={warning ? 'exclamationTriangleLine' : 'error'}
+                color={warning ? 'warning' : 'negative'}
+            />
+            <span className="icon-label">{error}</span>
+        </ListGroupItem>
+    );
 };
 
 export default SubmitErrorResponse;
index ac19072..72f8de0 100644 (file)
@@ -4,9 +4,9 @@
  * 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.
@@ -18,35 +18,38 @@ import React from 'react';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import PropTypes from 'prop-types';
 
-
 class Accordion extends React.Component {
+    static propTypes = {
+        title: PropTypes.string,
+        children: PropTypes.node
+    };
 
-       static propTypes = {
-               title: PropTypes.string,
-               children: PropTypes.node
-       }
-
-       constructor(props) {
-               super(props);
-               this.state = {
-                       open: false
-               };
-       }
-       render() {
-               const {children, title} = this.props; 
-               const {open} = this.state;
-               return (
-                       <div className='accordion'>
-                               <div onClick={()=>this.setState({open: !open})} className='accordion-header'>
-                                       <SVGIcon name='chevronUp' iconClassName={open ? 'down' : ''}/>          
-                                       <div className='title'>{title}</div>
-                               </div>
-                               <div className={`accordion-body ${open ? 'open' : ''}`}>
-                                       {children}
-                               </div>
-                       </div>
-               );
-       }
+    constructor(props) {
+        super(props);
+        this.state = {
+            open: false
+        };
+    }
+    render() {
+        const { children, title } = this.props;
+        const { open } = this.state;
+        return (
+            <div className="accordion">
+                <div
+                    onClick={() => this.setState({ open: !open })}
+                    className="accordion-header">
+                    <SVGIcon
+                        name="chevronUp"
+                        iconClassName={open ? 'down' : ''}
+                    />
+                    <div className="title">{title}</div>
+                </div>
+                <div className={`accordion-body ${open ? 'open' : ''}`}>
+                    {children}
+                </div>
+            </div>
+        );
+    }
 }
 
-export default Accordion;
\ No newline at end of file
+export default Accordion;
index 25e7e7e..b4bc8be 100644 (file)
@@ -5,72 +5,105 @@ import moment from 'moment';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 
 class CustomInput extends React.Component {
+    static propTypes = {
+        placeHolderText: PropTypes.string,
+        onChange: PropTypes.func,
+        onClick: PropTypes.func,
+        value: PropTypes.string
+    };
 
-       static propTypes = {
-               placeHolderText: PropTypes.string,
-               onChange: PropTypes.func,
-               onClick: PropTypes.func,
-               value: PropTypes.string
-       };
-
-       render() {
-               const {placeholderText, onClick, onClear, inputRef, value: date} = this.props;
-               const text = date ? date : placeholderText;
-               const textStyle = date ? '' : 'placeholder';
-               return (
-                       <div onClick={onClick} ref={inputRef} className='datepicker-custom-input'>
-                               <div  className={`datepicker-text ${textStyle}`}>{text}</div>
-                               {date && <SVGIcon onClick={e => {e.stopPropagation(); onClear();}} name='close' className='clear-input'/>}
-                               <SVGIcon name='calendar'/>
-                       </div>
-               );
-       }
-};
+    render() {
+        const {
+            placeholderText,
+            onClick,
+            onClear,
+            inputRef,
+            value: date
+        } = this.props;
+        const text = date ? date : placeholderText;
+        const textStyle = date ? '' : 'placeholder';
+        return (
+            <div
+                onClick={onClick}
+                ref={inputRef}
+                className="datepicker-custom-input">
+                <div className={`datepicker-text ${textStyle}`}>{text}</div>
+                {date && (
+                    <SVGIcon
+                        onClick={e => {
+                            e.stopPropagation();
+                            onClear();
+                        }}
+                        name="close"
+                        className="clear-input"
+                    />
+                )}
+                <SVGIcon name="calendar" />
+            </div>
+        );
+    }
+}
 
 const parseDate = (date, format) => {
-       return typeof date === 'number' ? moment.unix(date) : moment(date, format);
+    return typeof date === 'number' ? moment.unix(date) : moment(date, format);
 };
 
 class Datepicker extends React.Component {
-       static propTypes = {
-               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,
-                       disabled = false, inputRef} = this.props;
-               const placeholderText =  'Enter a date';
-               const props = {
-                       format,
-                       onChange,
-                       disabled,
-                       selected: date ? parseDate(date, format) : date,
-                       selectsStart,
-                       selectsEnd,
-                       placeholderText,
-                       startDate: startDate ? parseDate(startDate, format) : startDate,
-                       endDate: endDate ? parseDate(endDate, format) : endDate
-               };
+    static propTypes = {
+        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,
+            disabled = false,
+            inputRef
+        } = this.props;
+        const placeholderText = 'Enter a date';
+        const props = {
+            format,
+            onChange,
+            disabled,
+            selected: date ? parseDate(date, format) : date,
+            selectsStart,
+            selectsEnd,
+            placeholderText,
+            startDate: startDate ? parseDate(startDate, format) : startDate,
+            endDate: endDate ? parseDate(endDate, format) : endDate
+        };
 
-               return (
-                       <div className='customized-date-picker'>
-                               <DatePicker
-                                       calendarClassName='customized-date-picker-calendar'
-                                       customInput={<CustomInput inputRef={inputRef} onClear={() => onChange(undefined)} placeholderText={placeholderText}/>}
-                                       minDate={selectsEnd && props.startDate}
-                                       maxDate={selectsStart && props.endDate}
-                                       {...props}/>
-                       </div>
-               );
-       }
+        return (
+            <div className="customized-date-picker">
+                <DatePicker
+                    calendarClassName="customized-date-picker-calendar"
+                    customInput={
+                        <CustomInput
+                            inputRef={inputRef}
+                            onClear={() => onChange(undefined)}
+                            placeholderText={placeholderText}
+                        />
+                    }
+                    minDate={selectsEnd && props.startDate}
+                    maxDate={selectsStart && props.endDate}
+                    {...props}
+                />
+            </div>
+        );
+    }
 }
 
 export default Datepicker;
index 3c9ceed..9fcd704 100644 (file)
@@ -20,79 +20,106 @@ import VersionController from 'nfvo-components/panel/versionController/VersionCo
 import NavigationSideBar from 'nfvo-components/panel/NavigationSideBar.jsx';
 
 export default class TabulatedEditor extends React.Component {
+    render() {
+        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();
 
-       render() {
-               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();
+        if (onClose) {
+            versionControllerProps = {
+                ...versionControllerProps,
+                onClose: () => onClose(versionControllerProps)
+            };
+        }
+        return (
+            <div className="software-product-view">
+                <div className="software-product-navigation-side-bar">
+                    <NavigationSideBar
+                        {...navigationBarProps}
+                        onSelect={onNavigate}
+                        onToggle={onToggle}
+                    />
+                </div>
+                <div className="software-product-landing-view-right-side flex-column">
+                    <VersionController
+                        {...versionControllerProps}
+                        onVersionSwitching={version =>
+                            onVersionSwitching(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}`)}>
+                        {child}
+                    </div>
+                </div>
+            </div>
+        );
+    }
 
-               if(onClose) {
-                       versionControllerProps = {
-                               ...versionControllerProps,
-                               onClose: () => onClose(versionControllerProps)
-                       };
-               }
-               return (
-                       <div className='software-product-view'>
-                               <div className='software-product-navigation-side-bar'>
-                                       <NavigationSideBar {...navigationBarProps} onSelect={onNavigate} onToggle={onToggle}/>
-                               </div>
-                               <div className='software-product-landing-view-right-side flex-column'>
-                                       <VersionController
-                                               {...versionControllerProps}
-                                               onVersionSwitching={version => onVersionSwitching(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}`)}>
-                                       {
-                                               child
-                                       }
-                                       </div>
-                               </div>
-                       </div>
-               );
-       }
+    prepareChild() {
+        const { onSave, onCreate, children } = this.props;
 
-       prepareChild() {
-               const {onSave, onCreate, children} = this.props;
+        const additionalChildProps = { ref: 'editor' };
+        if (onSave) {
+            additionalChildProps.onSave = onSave;
+        }
+        if (onCreate) {
+            additionalChildProps.onCreate = onCreate;
+        }
 
-               const additionalChildProps = {ref: 'editor'};
-               if (onSave) {
-                       additionalChildProps.onSave = onSave;
-               }
-               if (onCreate) {
-                       additionalChildProps.onCreate = onCreate;
-               }
+        const child = React.cloneElement(
+            React.Children.only(children),
+            additionalChildProps
+        );
+        return child;
+    }
 
-               const child = React.cloneElement(React.Children.only(children), additionalChildProps);
-               return child;
-       }
+    handleSave = () => {
+        const childInstance = this.refs.editor.getWrappedInstance();
+        if (childInstance.save) {
+            return childInstance.save();
+        } else {
+            return this.props.onSave();
+        }
+    };
 
-
-
-       handleSave = () => {
-               const childInstance = this.refs.editor.getWrappedInstance();
-               if (childInstance.save) {
-                       return childInstance.save();
-               } else {
-                       return this.props.onSave();
-               }
-       };
-
-       handleCreate = () => {
-               const childInstance = this.refs.editor.getWrappedInstance();
-               if (childInstance.create) {
-                       childInstance.create();
-               } else {
-                       this.props.onCreate();
-               }
-       }
+    handleCreate = () => {
+        const childInstance = this.refs.editor.getWrappedInstance();
+        if (childInstance.create) {
+            childInstance.create();
+        } else {
+            this.props.onCreate();
+        }
+    };
 }
index 5b4e0a8..0d47d85 100644 (file)
  * or
  * https://github.com/JedWatson/react-select
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Button from 'sdc-ui/lib/react/Button.js';
 
 class DraggableUploadFileBox extends Component {
-       render() {
-               let {className, onClick, dataTestId, isReadOnlyMode} = this.props;
-               return (
-                       <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}>{i18n('Select File')}</Button>
-                       </div>
-               );
-       }
+    render() {
+        let { className, onClick, dataTestId, isReadOnlyMode } = this.props;
+        return (
+            <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}>
+                    {i18n('Select File')}
+                </Button>
+            </div>
+        );
+    }
 }
 export default DraggableUploadFileBox;
index c62e042..9723cde 100644 (file)
  */
 import React from 'react';
 
-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>
-       </div>
+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>
+    </div>
 );
 
 export default GridItem;
index 8f4a024..f2e3588 100644 (file)
@@ -17,21 +17,32 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import classnames from 'classnames';
 
-const GridSection = ({title, children, className = '', titleClassName, hasLastColSet = false}) => {
-       return (
-               <div className={classnames('grid-section', className, {'has-last-col-set': hasLastColSet})}>
-                       {title && <div className={`section-title ${titleClassName || ''}`}>{title}</div>}
-                       <div className='grid-items'>
-                               {children}
-                       </div>
-               </div>
-       );
+const GridSection = ({
+    title,
+    children,
+    className = '',
+    titleClassName,
+    hasLastColSet = false
+}) => {
+    return (
+        <div
+            className={classnames('grid-section', className, {
+                'has-last-col-set': hasLastColSet
+            })}>
+            {title && (
+                <div className={`section-title ${titleClassName || ''}`}>
+                    {title}
+                </div>
+            )}
+            <div className="grid-items">{children}</div>
+        </div>
+    );
 };
 
 GridSection.propTypes = {
-       title: PropTypes.string,
-       titleClassName: PropTypes.string,
-       hasLastColSet: PropTypes.bool
+    title: PropTypes.string,
+    titleClassName: PropTypes.string,
+    hasLastColSet: PropTypes.bool
 };
 
 export default GridSection;
index 82fbe1d..3973ae8 100644 (file)
@@ -19,99 +19,118 @@ import ReactDOM from 'react-dom';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
 
-const ExpandableInputClosed = ({iconType, onClick}) => (
-       <SVGIcon className='expandable-input-wrapper closed'  data-test-id='expandable-input-closed' name={iconType} onClick={onClick} />
+const ExpandableInputClosed = ({ iconType, onClick }) => (
+    <SVGIcon
+        className="expandable-input-wrapper closed"
+        data-test-id="expandable-input-closed"
+        name={iconType}
+        onClick={onClick}
+    />
 );
 
 class ExpandableInputOpened extends React.Component {
-       componentDidMount(){
-               this.rawDomNode = ReactDOM.findDOMNode(this.searchInputNode.inputWrapper);
-               this.rawDomNode.focus();
-       }
+    componentDidMount() {
+        this.rawDomNode = ReactDOM.findDOMNode(
+            this.searchInputNode.inputWrapper
+        );
+        this.rawDomNode.focus();
+    }
 
-       componentWillReceiveProps(newProps){
-               if (!newProps.value){
-                       if (!(document.activeElement === this.rawDomNode)){
-                               this.props.handleBlur();
-                       }
-               }
-       }
+    componentWillReceiveProps(newProps) {
+        if (!newProps.value) {
+            if (!(document.activeElement === this.rawDomNode)) {
+                this.props.handleBlur();
+            }
+        }
+    }
 
-       handleClose(){
-               this.props.onChange('');
-               this.rawDomNode.focus();
-       }
+    handleClose() {
+        this.props.onChange('');
+        this.rawDomNode.focus();
+    }
 
-       handleKeyDown(e){
-               if (e.key === 'Escape'){
-                       e.preventDefault();
-                       if (this.props.value) {
-                               this.handleClose();
-                       } else {
-                               this.rawDomNode.blur();
-                       }
-               };
-       }
+    handleKeyDown(e) {
+        if (e.key === 'Escape') {
+            e.preventDefault();
+            if (this.props.value) {
+                this.handleClose();
+            } else {
+                this.rawDomNode.blur();
+            }
+        }
+    }
 
-       render() {
-               let {iconType, value, onChange, handleBlur} = this.props;
-               return (
-                               <div className='expandable-input-wrapper opened' key='expandable'>
-                                       <Input
-                                               type='text'
-                                               data-test-id='expandable-input-opened'
-                                               value={value}
-                                               ref={(input) => this.searchInputNode = input}
-                                               className='expandable-active'
-                                               groupClassName='expandable-input-control'
-                                               onChange={e => onChange(e)}
-                                               onKeyDown={e => this.handleKeyDown(e)}
-                                               onBlur={handleBlur}/>
-                                       {value && <SVGIcon data-test-id='expandable-input-close-btn' onClick={() => this.handleClose()} name='close' />}
-                                       {!value && <SVGIcon name={iconType} onClick={handleBlur}/>}
-                               </div>
-               );
-       }
+    render() {
+        let { iconType, value, onChange, handleBlur } = this.props;
+        return (
+            <div className="expandable-input-wrapper opened" key="expandable">
+                <Input
+                    type="text"
+                    data-test-id="expandable-input-opened"
+                    value={value}
+                    ref={input => (this.searchInputNode = input)}
+                    className="expandable-active"
+                    groupClassName="expandable-input-control"
+                    onChange={e => onChange(e)}
+                    onKeyDown={e => this.handleKeyDown(e)}
+                    onBlur={handleBlur}
+                />
+                {value && (
+                    <SVGIcon
+                        data-test-id="expandable-input-close-btn"
+                        onClick={() => this.handleClose()}
+                        name="close"
+                    />
+                )}
+                {!value && <SVGIcon name={iconType} onClick={handleBlur} />}
+            </div>
+        );
+    }
 }
 
 class ExpandableInput extends React.Component {
+    static propTypes = {
+        iconType: PropTypes.string,
+        onChange: PropTypes.func,
+        value: PropTypes.string
+    };
 
-       static propTypes = {
-               iconType: PropTypes.string,
-               onChange: PropTypes.func,
-               value: PropTypes.string
-       };
+    state = { showInput: false };
 
-       state = {showInput: false};
+    closeInput() {
+        if (!this.props.value) {
+            this.setState({ showInput: false });
+        }
+    }
 
-       closeInput(){
-               if (!this.props.value) {
-                       this.setState({showInput: false});
-               }
-       }
+    getValue() {
+        return this.props.value;
+    }
 
-       getValue(){
-               return this.props.value;
-       }
-
-       render(){
-               let {iconType, value, onChange = false} = this.props;
-               return (
-                       <div className='expandable-input-top'>
-                               {this.state.showInput &&
-                                       <ExpandableInputOpened
-                                               key='open'
-                                               iconType={iconType}
-                                               onChange={onChange}
-                                               value={value}
-                                               handleKeyDown={(e) => this.handleKeyDown(e)}
-                                               handleBlur={() => this.closeInput()}/>
-                               }
-                               {!this.state.showInput && <ExpandableInputClosed key='closed' iconType={iconType} onClick={() => this.setState({showInput: true})} />}
-                       </div>
-                               );
-       }
+    render() {
+        let { iconType, value, onChange = false } = this.props;
+        return (
+            <div className="expandable-input-top">
+                {this.state.showInput && (
+                    <ExpandableInputOpened
+                        key="open"
+                        iconType={iconType}
+                        onChange={onChange}
+                        value={value}
+                        handleKeyDown={e => this.handleKeyDown(e)}
+                        handleBlur={() => this.closeInput()}
+                    />
+                )}
+                {!this.state.showInput && (
+                    <ExpandableInputClosed
+                        key="closed"
+                        iconType={iconType}
+                        onClick={() => this.setState({ showInput: true })}
+                    />
+                )}
+            </div>
+        );
+    }
 }
 
-
 export default ExpandableInput;
index 03c7273..b0e0d87 100644 (file)
  * or
  * https://github.com/JedWatson/react-select
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import Select from 'react-select';
 
 class SelectInput extends Component {
+    inputValue = [];
 
-       inputValue = [];
+    render() {
+        let { label, value, ...other } = this.props;
+        const dataTestId = this.props['data-test-id']
+            ? { 'data-test-id': this.props['data-test-id'] }
+            : {};
+        return (
+            <div
+                {...dataTestId}
+                className="validation-input-wrapper dropdown-multi-select">
+                <div className="form-group">
+                    {label && <label className="control-label">{label}</label>}
+                    <Select
+                        ref="_myInput"
+                        onChange={value => this.onSelectChanged(value)}
+                        {...other}
+                        value={value}
+                    />
+                </div>
+            </div>
+        );
+    }
 
-       render() {
-               let {label, value, ...other} = this.props;
-               const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
-               return (
-                       <div  {...dataTestId} className='validation-input-wrapper dropdown-multi-select'>
-                               <div className='form-group'>
-                                       {label && <label className='control-label'>{label}</label>}
-                                       <Select ref='_myInput' onChange={value => this.onSelectChanged(value)} {...other} value={value} />
-                               </div>
-                       </div>
-               );
-       }
+    getValue() {
+        return this.inputValue && this.inputValue.length ? this.inputValue : '';
+    }
 
-       getValue() {
-               return this.inputValue && this.inputValue.length ? this.inputValue : '';
-       }
+    onSelectChanged(value) {
+        this.props.onMultiSelectChanged(value);
+    }
 
-       onSelectChanged(value) {
-               this.props.onMultiSelectChanged(value);
-       }
-
-       componentDidMount() {
-               let {value} = this.props;
-               this.inputValue = value ? value : [];
-       }
-       componentDidUpdate() {
-               if (this.inputValue !== this.props.value) {
-                       this.inputValue = this.props.value;
-               }
-       }
+    componentDidMount() {
+        let { value } = this.props;
+        this.inputValue = value ? value : [];
+    }
+    componentDidUpdate() {
+        if (this.inputValue !== this.props.value) {
+            this.inputValue = this.props.value;
+        }
+    }
 }
 
 export default SelectInput;
index 31a8a66..947570f 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 
-export default
-class ToggleInput extends React.Component {
+export default class ToggleInput extends React.Component {
+    static propTypes = {
+        label: PropTypes.node,
+        value: PropTypes.bool,
+        onChange: PropTypes.func,
+        disabled: PropTypes.bool
+    };
 
-       static propTypes = {
-               label: PropTypes.node,
-               value: PropTypes.bool,
-               onChange: PropTypes.func,
-               disabled: PropTypes.bool
-       }
+    static defaultProps = {
+        value: false,
+        label: ''
+    };
 
-       static defaultProps = {
-               value: false,
-               label: ''
-       }
+    state = {
+        value: this.props.value
+    };
 
-       state = {
-               value: this.props.value
-       }
+    status() {
+        return this.state.value ? 'on' : 'off';
+    }
 
-       status() {
-               return this.state.value ? 'on' : 'off';
-       }
+    render() {
+        let { label, disabled } = this.props;
+        let checked = this.status() === 'on';
+        //TODO check onclick
+        return (
+            <div
+                className="toggle-input-wrapper form-group"
+                onClick={!disabled && this.click}>
+                <div className="toggle-input-label">{label}</div>
+                <div className="toggle-switch">
+                    <input
+                        className="toggle toggle-round-flat"
+                        type="checkbox"
+                        checked={checked}
+                        readOnly
+                    />
+                    <label />
+                </div>
+            </div>
+        );
+    }
 
-       render() {
-               let {label, disabled} = this.props;
-               let checked = this.status() === 'on';
-               //TODO check onclick
-               return (
-                       <div className='toggle-input-wrapper form-group' onClick={!disabled && this.click}>
-                               <div className='toggle-input-label'>{label}</div>
-                               <div className='toggle-switch'>
-                                       <input className='toggle toggle-round-flat' type='checkbox' checked={checked} readOnly/>
-                                       <label></label>
-                               </div>
-                       </div>
-               );
-       }
+    click = () => {
+        let value = !this.state.value;
+        this.setState({ value });
 
-       click = () => {
-               let value = !this.state.value;
-               this.setState({value});
+        let onChange = this.props.onChange;
+        if (onChange) {
+            onChange(value);
+        }
+    };
 
-               let onChange = this.props.onChange;
-               if (onChange) {
-                       onChange(value);
-               }
-       }
-
-       getValue() {
-               return this.state.value;
-       }
+    getValue() {
+        return this.state.value;
+    }
 }
index a689c50..7ab4c82 100644 (file)
@@ -19,136 +19,224 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
 
 class DualListboxView extends React.Component {
-
-       static propTypes = {
-
-               availableList: PropTypes.arrayOf(PropTypes.shape({
-                       id: PropTypes.string.isRequired,
-                       name: PropTypes.string.isRequired
-               })),
-               filterTitle: PropTypes.shape({
-                       left: PropTypes.string,
-                       right: PropTypes.string
-               }),
-               selectedValuesList: PropTypes.arrayOf(PropTypes.string),
-
-               onChange: PropTypes.func.isRequired
-       };
-
-       static defaultProps = {
-               selectedValuesList: [],
-               availableList: [],
-               filterTitle: {
-                       left: '',
-                       right: ''
-               }
-       };
-
-       state = {
-               availableListFilter: '',
-               selectedValuesListFilter: '',
-               selectedValues: []
-       };
-
-       render() {
-               let {availableList, selectedValuesList, filterTitle, isReadOnlyMode} = this.props;
-               let {availableListFilter, selectedValuesListFilter} = this.state;
-
-               let unselectedList = availableList.filter(availableItem => !selectedValuesList.find(value => value === availableItem.id));
-               let selectedList = availableList.filter(availableItem => selectedValuesList.find(value => value === availableItem.id));
-               selectedList = selectedList.sort((a, b) => selectedValuesList.indexOf(a.id) - selectedValuesList.indexOf(b.id));
-               return (
-                       <div className='dual-list-box'>
-                               {this.renderListbox(filterTitle.left, unselectedList, {
-                                       value: availableListFilter,
-                                       ref: 'availableListFilter',
-                                       disabled: isReadOnlyMode,
-                                       onChange: (value) => this.setState({availableListFilter: value})
-                               }, {ref: 'availableValues', disabled: isReadOnlyMode, testId: 'available',})}
-                               {this.renderOperationsBar(isReadOnlyMode)}
-                               {this.renderListbox(filterTitle.right, selectedList, {
-                                       value: selectedValuesListFilter,
-                                       ref: 'selectedValuesListFilter',
-                                       disabled: isReadOnlyMode,
-                                       onChange: (value) => this.setState({selectedValuesListFilter: value})
-                               }, {ref: 'selectedValues', disabled: isReadOnlyMode, testId: 'selected'})}
-                       </div>
-               );
-       }
-
-       renderListbox(filterTitle, list, filterProps, props) {
-               let regExFilter = new RegExp(escape(filterProps.value), 'i');
-               let matchedItems = list.filter(item => item.name.match(regExFilter));
-               let unMatchedItems = list.filter(item => !item.name.match(regExFilter));
-               return (
-                       <div className='dual-search-multi-select-section'>
-                               <p>{filterTitle}</p>
-                               <div className='dual-text-box-search search-wrapper'>
-                                       <Input data-test-id={`${props.testId}-search-input`}
-                                                  name='search-input-control' type='text'
-                                                  groupClassName='search-input-control'
-                                                  {...filterProps}/>
-                                       <SVGIcon name='search' className='search-icon'/>
-                               </div>
-                               <Input
-                                       multiple
-                                       onChange={(event) => this.onSelectItems(event.target.selectedOptions)}
-                                       groupClassName='dual-list-box-multi-select'
-                                       type='select'
-                                       name='dual-list-box-multi-select'
-                                       data-test-id={`${props.testId}-select-input`}
-                                       disabled={props.disabled}
-                                       ref={props.ref}>
-                                       {matchedItems.map(item => this.renderOption(item.id, item.name))}
-                                       {matchedItems.length && unMatchedItems.length && <option style={{pointerEvents: 'none'}}>--------------------</option>}
-                                       {unMatchedItems.map(item => this.renderOption(item.id, item.name))}
-                               </Input>
-                       </div>
-               );
-       }
-
-       onSelectItems(selectedOptions) {
-               let selectedValues = Object.keys(selectedOptions).map((k) => selectedOptions[k].value);
-               this.setState({selectedValues});
-       }
-
-       renderOption(value, name) {
-               return (<option className='dual-list-box-multi-select-text' key={value} value={value}>{name}</option>);
-       }
-
-       renderOperationsBar(isReadOnlyMode) {
-               return (
-                       <div className={`dual-list-options-bar${isReadOnlyMode ? ' disabled' : ''}`}>
-                               {this.renderOperationBarButton(() => this.addToSelectedList(), 'angleRight')}
-                               {this.renderOperationBarButton(() => this.removeFromSelectedList(), 'angleLeft')}
-                               {this.renderOperationBarButton(() => this.addAllToSelectedList(), 'angleDoubleRight')}
-                               {this.renderOperationBarButton(() => this.removeAllFromSelectedList(), 'angleDoubleLeft')}
-                       </div>
-               );
-       }
-
-       renderOperationBarButton(onClick, iconName){
-               return (<div className='dual-list-option' data-test-id={`operation-icon-${iconName}`} onClick={onClick}><SVGIcon name={iconName}/></div>);
-       }
-
-       addToSelectedList() {
-               this.props.onChange(this.props.selectedValuesList.concat(this.state.selectedValues));
-               this.setState({selectedValues: []});
-       }
-
-       removeFromSelectedList() {
-               const selectedValues = this.state.selectedValues;
-               this.props.onChange(this.props.selectedValuesList.filter(value => !selectedValues.find(selectedValue => selectedValue === value)));
-               this.setState({selectedValues: []});
-       }
-
-       addAllToSelectedList() {
-               this.props.onChange(this.props.availableList.map(item => item.id));
-       }
-
-       removeAllFromSelectedList() {
-               this.props.onChange([]);
-       }
+    static propTypes = {
+        availableList: PropTypes.arrayOf(
+            PropTypes.shape({
+                id: PropTypes.string.isRequired,
+                name: PropTypes.string.isRequired
+            })
+        ),
+        filterTitle: PropTypes.shape({
+            left: PropTypes.string,
+            right: PropTypes.string
+        }),
+        selectedValuesList: PropTypes.arrayOf(PropTypes.string),
+
+        onChange: PropTypes.func.isRequired
+    };
+
+    static defaultProps = {
+        selectedValuesList: [],
+        availableList: [],
+        filterTitle: {
+            left: '',
+            right: ''
+        }
+    };
+
+    state = {
+        availableListFilter: '',
+        selectedValuesListFilter: '',
+        selectedValues: []
+    };
+
+    render() {
+        let {
+            availableList,
+            selectedValuesList,
+            filterTitle,
+            isReadOnlyMode
+        } = this.props;
+        let { availableListFilter, selectedValuesListFilter } = this.state;
+
+        let unselectedList = availableList.filter(
+            availableItem =>
+                !selectedValuesList.find(value => value === availableItem.id)
+        );
+        let selectedList = availableList.filter(availableItem =>
+            selectedValuesList.find(value => value === availableItem.id)
+        );
+        selectedList = selectedList.sort(
+            (a, b) =>
+                selectedValuesList.indexOf(a.id) -
+                selectedValuesList.indexOf(b.id)
+        );
+        return (
+            <div className="dual-list-box">
+                {this.renderListbox(
+                    filterTitle.left,
+                    unselectedList,
+                    {
+                        value: availableListFilter,
+                        ref: 'availableListFilter',
+                        disabled: isReadOnlyMode,
+                        onChange: value =>
+                            this.setState({ availableListFilter: value })
+                    },
+                    {
+                        ref: 'availableValues',
+                        disabled: isReadOnlyMode,
+                        testId: 'available'
+                    }
+                )}
+                {this.renderOperationsBar(isReadOnlyMode)}
+                {this.renderListbox(
+                    filterTitle.right,
+                    selectedList,
+                    {
+                        value: selectedValuesListFilter,
+                        ref: 'selectedValuesListFilter',
+                        disabled: isReadOnlyMode,
+                        onChange: value =>
+                            this.setState({ selectedValuesListFilter: value })
+                    },
+                    {
+                        ref: 'selectedValues',
+                        disabled: isReadOnlyMode,
+                        testId: 'selected'
+                    }
+                )}
+            </div>
+        );
+    }
+
+    renderListbox(filterTitle, list, filterProps, props) {
+        let regExFilter = new RegExp(escape(filterProps.value), 'i');
+        let matchedItems = list.filter(item => item.name.match(regExFilter));
+        let unMatchedItems = list.filter(item => !item.name.match(regExFilter));
+        return (
+            <div className="dual-search-multi-select-section">
+                <p>{filterTitle}</p>
+                <div className="dual-text-box-search search-wrapper">
+                    <Input
+                        data-test-id={`${props.testId}-search-input`}
+                        name="search-input-control"
+                        type="text"
+                        groupClassName="search-input-control"
+                        {...filterProps}
+                    />
+                    <SVGIcon name="search" className="search-icon" />
+                </div>
+                <Input
+                    multiple
+                    onChange={event =>
+                        this.onSelectItems(event.target.selectedOptions)
+                    }
+                    groupClassName="dual-list-box-multi-select"
+                    type="select"
+                    name="dual-list-box-multi-select"
+                    data-test-id={`${props.testId}-select-input`}
+                    disabled={props.disabled}
+                    ref={props.ref}>
+                    {matchedItems.map(item =>
+                        this.renderOption(item.id, item.name)
+                    )}
+                    {matchedItems.length &&
+                        unMatchedItems.length && (
+                            <option style={{ pointerEvents: 'none' }}>
+                                --------------------
+                            </option>
+                        )}
+                    {unMatchedItems.map(item =>
+                        this.renderOption(item.id, item.name)
+                    )}
+                </Input>
+            </div>
+        );
+    }
+
+    onSelectItems(selectedOptions) {
+        let selectedValues = Object.keys(selectedOptions).map(
+            k => selectedOptions[k].value
+        );
+        this.setState({ selectedValues });
+    }
+
+    renderOption(value, name) {
+        return (
+            <option
+                className="dual-list-box-multi-select-text"
+                key={value}
+                value={value}>
+                {name}
+            </option>
+        );
+    }
+
+    renderOperationsBar(isReadOnlyMode) {
+        return (
+            <div
+                className={`dual-list-options-bar${
+                    isReadOnlyMode ? ' disabled' : ''
+                }`}>
+                {this.renderOperationBarButton(
+                    () => this.addToSelectedList(),
+                    'angleRight'
+                )}
+                {this.renderOperationBarButton(
+                    () => this.removeFromSelectedList(),
+                    'angleLeft'
+                )}
+                {this.renderOperationBarButton(
+                    () => this.addAllToSelectedList(),
+                    'angleDoubleRight'
+                )}
+                {this.renderOperationBarButton(
+                    () => this.removeAllFromSelectedList(),
+                    'angleDoubleLeft'
+                )}
+            </div>
+        );
+    }
+
+    renderOperationBarButton(onClick, iconName) {
+        return (
+            <div
+                className="dual-list-option"
+                data-test-id={`operation-icon-${iconName}`}
+                onClick={onClick}>
+                <SVGIcon name={iconName} />
+            </div>
+        );
+    }
+
+    addToSelectedList() {
+        this.props.onChange(
+            this.props.selectedValuesList.concat(this.state.selectedValues)
+        );
+        this.setState({ selectedValues: [] });
+    }
+
+    removeFromSelectedList() {
+        const selectedValues = this.state.selectedValues;
+        this.props.onChange(
+            this.props.selectedValuesList.filter(
+                value =>
+                    !selectedValues.find(
+                        selectedValue => selectedValue === value
+                    )
+            )
+        );
+        this.setState({ selectedValues: [] });
+    }
+
+    addAllToSelectedList() {
+        this.props.onChange(this.props.availableList.map(item => item.id));
+    }
+
+    removeAllFromSelectedList() {
+        this.props.onChange([]);
+    }
 }
 
 export default DualListboxView;
index 6df0bf9..62fc29a 100644 (file)
@@ -19,130 +19,160 @@ import PropTypes from 'prop-types';
 import ValidationButtons from './ValidationButtons.jsx';
 
 class Form extends React.Component {
-
-       static defaultProps = {
-               hasButtons : true,
-               onSubmit : null,
-               onReset :  null,
-               labledButtons: true,
-               onValidChange :  null,
-               isValid: true,
-               submitButtonText: null,
-               cancelButtonText: null
-       };
-
-       static propTypes = {
-               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) {
-               super(props);
-       }
-
-
-       render() {
-               // eslint-disable-next-line no-unused-vars
-               let {isValid, onValidChange, onValidityChanged, onDataChanged, formReady, onValidateForm, isReadOnlyMode, hasButtons, onSubmit, labledButtons, submitButtonText,
-                        cancelButtonText, children, ...formProps} = this.props;
-               return (
-                       <form {...formProps} ref={(form) => this.form = form} onSubmit={event => this.handleFormValidation(event)}>
-                               <div className='validation-form-content'>
-                                       <fieldset disabled={isReadOnlyMode}>
-                                               {children}
-                                       </fieldset>
-                               </div>
-                               {hasButtons && 
-                                       <ValidationButtons 
-                                               labledButtons={labledButtons} 
-                                               submitButtonText={submitButtonText} 
-                                               cancelButtonText={cancelButtonText} 
-                                               ref={(buttons) => this.buttons = buttons} 
-                                               isReadOnlyMode={isReadOnlyMode}/>}
-                       </form>
-               );
-       }
-
-       handleFormValidation(event) {
-               event.preventDefault();
-               if (this.props.onValidateForm && !this.props.formReady){
-                       return this.props.onValidateForm();
-               } else {
-                       return this.handleFormSubmit(event);
-               }
-       }
-       handleFormSubmit(event) {
-               if (event) {
-                       event.preventDefault();
-               }
-               if(this.props.onSubmit) {
-                       return this.props.onSubmit(event);
-               }
-       }
-
-       componentDidMount() {
-               if (this.props.hasButtons) {
-                       this.buttons.setState({isValid: this.props.isValid});
-               }
-       }
-
-
-
-       componentDidUpdate(prevProps) {
-               // only handling this programatically if the validation of the form is done outside of the view
-               // (example with a form that is dependent on the state of other forms)
-               if (prevProps.isValid !== this.props.isValid) {
-                       if (this.props.hasButtons) {
-                               this.buttons.setState({isValid: this.props.isValid});
-                       }
-                       // callback in case form is part of bigger picture in view
-                       if (this.props.onValidChange) {
-                               this.props.onValidChange(this.props.isValid);
-                       }
-
-                       // TODO - maybe this has to be part of componentWillUpdate
-                       if(this.props.onValidityChanged) {
-                               this.props.onValidityChanged(this.props.isValid);
-                       }
-               }
-               if (this.props.formReady) { // if form validation succeeded -> continue with submit
-                       this.handleFormSubmit();
-               }
-       }
-
+    static defaultProps = {
+        hasButtons: true,
+        onSubmit: null,
+        onReset: null,
+        labledButtons: true,
+        onValidChange: null,
+        isValid: true,
+        submitButtonText: null,
+        cancelButtonText: null
+    };
+
+    static propTypes = {
+        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) {
+        super(props);
+    }
+    render() {
+        /* eslint-disable no-unused-vars */
+        let {
+            isValid,
+            onValidChange,
+            onValidityChanged,
+            onDataChanged,
+            formReady,
+            onValidateForm,
+            isReadOnlyMode,
+            hasButtons,
+            onSubmit,
+            labledButtons,
+            submitButtonText,
+            cancelButtonText,
+            children,
+            ...formProps
+        } = this.props;
+        /* eslint-enable no-unused-vars */
+        return (
+            <form
+                {...formProps}
+                ref={form => (this.form = form)}
+                onSubmit={event => this.handleFormValidation(event)}>
+                <div className="validation-form-content">
+                    <fieldset disabled={isReadOnlyMode}>{children}</fieldset>
+                </div>
+                {hasButtons && (
+                    <ValidationButtons
+                        labledButtons={labledButtons}
+                        submitButtonText={submitButtonText}
+                        cancelButtonText={cancelButtonText}
+                        ref={buttons => (this.buttons = buttons)}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                )}
+            </form>
+        );
+    }
+
+    handleFormValidation(event) {
+        event.preventDefault();
+        if (this.props.onValidateForm && !this.props.formReady) {
+            return this.props.onValidateForm();
+        } else {
+            return this.handleFormSubmit(event);
+        }
+    }
+    handleFormSubmit(event) {
+        if (event) {
+            event.preventDefault();
+        }
+        if (this.props.onSubmit) {
+            return this.props.onSubmit(event);
+        }
+    }
+
+    componentDidMount() {
+        if (this.props.hasButtons) {
+            this.buttons.setState({ isValid: this.props.isValid });
+        }
+    }
+
+    componentDidUpdate(prevProps) {
+        // only handling this programatically if the validation of the form is done outside of the view
+        // (example with a form that is dependent on the state of other forms)
+        if (prevProps.isValid !== this.props.isValid) {
+            if (this.props.hasButtons) {
+                this.buttons.setState({ isValid: this.props.isValid });
+            }
+            // callback in case form is part of bigger picture in view
+            if (this.props.onValidChange) {
+                this.props.onValidChange(this.props.isValid);
+            }
+
+            // TODO - maybe this has to be part of componentWillUpdate
+            if (this.props.onValidityChanged) {
+                this.props.onValidityChanged(this.props.isValid);
+            }
+        }
+        if (this.props.formReady) {
+            // if form validation succeeded -> continue with submit
+            this.handleFormSubmit();
+        }
+    }
 }
 
 export class TabsForm extends Form {
-       render() {
-               // eslint-disable-next-line no-unused-vars
-               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}
-                                               submitButtonText={submitButtonText}
-                                               cancelButtonText={cancelButtonText}
-                                               ref={buttons => this.buttons = buttons}
-                                               isReadOnlyMode={isReadOnlyMode}/>
-                               }
-                       </form>
-               );
-       }
+    render() {
+        /* eslint-disable no-unused-vars */
+        let {
+            submitButtonText,
+            cancelButtonText,
+            isValid,
+            formReady,
+            onValidateForm,
+            isReadOnlyMode,
+            hasButtons,
+            onSubmit,
+            labledButtons,
+            onValidChange,
+            onValidityChanged,
+            onDataChanged,
+            children,
+            ...formProps
+        } = this.props;
+        /* eslint-enable no-unused-vars */
+        return (
+            <form
+                {...formProps}
+                ref={form => (this.form = form)}
+                onSubmit={event => this.handleFormValidation(event)}>
+                <div className="validation-form-content">{children}</div>
+                {hasButtons && (
+                    <ValidationButtons
+                        labledButtons={labledButtons}
+                        submitButtonText={submitButtonText}
+                        cancelButtonText={cancelButtonText}
+                        ref={buttons => (this.buttons = buttons)}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                )}
+            </form>
+        );
+    }
 }
 
 export default Form;
index 33cea93..a5d6f4f 100644 (file)
@@ -25,191 +25,249 @@ import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 import Datepicker from 'nfvo-components/datepicker/Datepicker.jsx';
 
 class Input extends React.Component {
+    state = {
+        value: this.props.value,
+        checked: this.props.checked,
+        selectedValues: []
+    };
 
-       state = {
-               value: this.props.value,
-               checked: this.props.checked,
-               selectedValues: []
-       };
+    render() {
+        /* eslint-disable no-unused-vars */
+        const {
+            label,
+            isReadOnlyMode,
+            value,
+            onBlur,
+            onKeyDown,
+            type,
+            disabled,
+            checked,
+            name
+        } = this.props;
+        const {
+            groupClassName,
+            isValid = true,
+            errorText,
+            isRequired,
+            overlayPos,
+            ...inputProps
+        } = this.props;
+        const {
+            dateFormat,
+            startDate,
+            endDate,
+            selectsStart,
+            selectsEnd
+        } = this.props; // Date Props
+        /* eslint-enable no-unused-vars */
+        let wrapperClassName =
+            type !== 'radio'
+                ? 'validation-input-wrapper'
+                : 'validation-radio-wrapper';
+        if (disabled) {
+            wrapperClassName += ' disabled';
+        }
+        return (
+            <div className={wrapperClassName}>
+                <FormGroup
+                    className={classNames('form-group', [groupClassName], {
+                        required: isRequired,
+                        'has-error': !isValid
+                    })}>
+                    {label &&
+                        (type !== 'checkbox' && type !== 'radio') && (
+                            <label className="control-label">{label}</label>
+                        )}
+                    {type === 'text' && (
+                        <FormControl
+                            bsClass={'form-control input-options-other'}
+                            onChange={e => this.onChange(e)}
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            onBlur={onBlur}
+                            onKeyDown={onKeyDown}
+                            value={value || ''}
+                            inputRef={input => (this.input = input)}
+                            type={type}
+                            data-test-id={this.props['data-test-id']}
+                        />
+                    )}
+                    {type === 'number' && (
+                        <FormControl
+                            bsClass={'form-control input-options-other'}
+                            onChange={e => this.onChange(e)}
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            onBlur={onBlur}
+                            onKeyDown={onKeyDown}
+                            value={value !== undefined ? value : ''}
+                            inputRef={input => (this.input = input)}
+                            type={type}
+                            data-test-id={this.props['data-test-id']}
+                        />
+                    )}
 
-       render() {
-               const {label, isReadOnlyMode, value, onBlur, onKeyDown, type, disabled, checked, name} = this.props;
-               // eslint-disable-next-line no-unused-vars
-               const {groupClassName, isValid = true, errorText, isRequired,  overlayPos, ...inputProps} = this.props;
-               const {dateFormat, startDate, endDate, selectsStart, selectsEnd} = this.props; // Date Props
-               let wrapperClassName = (type !== 'radio') ? 'validation-input-wrapper' : 'validation-radio-wrapper';
-               if (disabled) {
-                       wrapperClassName += ' disabled';
-               }
-               return(
-                       <div className={wrapperClassName}>
-                               <FormGroup className={classNames('form-group', [groupClassName], {'required' : isRequired , 'has-error' : !isValid})} >
-                                       {(label && (type !== 'checkbox' && type !== 'radio')) && <label className='control-label'>{label}</label>}
-                                       {type === 'text'  &&
-                                       <FormControl
-                                               bsClass={'form-control input-options-other'}
-                                               onChange={(e) => this.onChange(e)}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               onBlur={onBlur}
-                                               onKeyDown={onKeyDown}
-                                               value={value || ''}
-                                               inputRef={(input) => this.input = input}
-                                               type={type}
-                                               data-test-id={this.props['data-test-id']}/>}
-                                       {type === 'number' &&
-                                       <FormControl
-                                               bsClass={'form-control input-options-other'}
-                                               onChange={(e) => this.onChange(e)}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               onBlur={onBlur}
-                                               onKeyDown={onKeyDown}
-                                               value={(value !== undefined) ? value : ''}
-                                               inputRef={(input) => this.input = input}
-                                               type={type}
-                                               data-test-id={this.props['data-test-id']}/>}
+                    {type === 'textarea' && (
+                        <FormControl
+                            className="form-control input-options-other"
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            value={value || ''}
+                            onBlur={onBlur}
+                            onKeyDown={onKeyDown}
+                            componentClass={type}
+                            onChange={e => this.onChange(e)}
+                            inputRef={input => (this.input = input)}
+                            data-test-id={this.props['data-test-id']}
+                        />
+                    )}
 
-                                       {type === 'textarea' &&
-                                       <FormControl
-                                               className='form-control input-options-other'
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               value={value || ''}
-                                               onBlur={onBlur}
-                                               onKeyDown={onKeyDown}
-                                               componentClass={type}
-                                               onChange={(e) => this.onChange(e)}
-                                               inputRef={(input) => this.input = input}
-                                               data-test-id={this.props['data-test-id']}/>}
+                    {type === 'checkbox' && (
+                        <Checkbox
+                            className={classNames({
+                                required: isRequired,
+                                'has-error': !isValid
+                            })}
+                            onChange={e => this.onChangeCheckBox(e)}
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            checked={checked}
+                            data-test-id={this.props['data-test-id']}>
+                            {label}
+                        </Checkbox>
+                    )}
 
-                                       {type === 'checkbox' &&
-                                       <Checkbox
-                                               className={classNames({'required' : isRequired , 'has-error' : !isValid})}
-                                               onChange={(e)=>this.onChangeCheckBox(e)}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               checked={checked}
-                                               data-test-id={this.props['data-test-id']}>{label}</Checkbox>}
+                    {type === 'radio' && (
+                        <Radio
+                            name={name}
+                            checked={checked}
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            value={value}
+                            onChange={isChecked =>
+                                this.onChangeRadio(isChecked)
+                            }
+                            inputRef={input => (this.input = input)}
+                            label={label}
+                            data-test-id={this.props['data-test-id']}
+                        />
+                    )}
+                    {type === 'select' && (
+                        <FormControl
+                            onClick={e => this.optionSelect(e)}
+                            className="custom-select"
+                            componentClass={type}
+                            inputRef={input => (this.input = input)}
+                            name={name}
+                            {...inputProps}
+                            data-test-id={this.props['data-test-id']}
+                        />
+                    )}
+                    {type === 'date' && (
+                        <Datepicker
+                            date={value}
+                            format={dateFormat}
+                            startDate={startDate}
+                            endDate={endDate}
+                            inputRef={input => (this.input = input)}
+                            onChange={this.props.onChange}
+                            disabled={isReadOnlyMode || Boolean(disabled)}
+                            data-test-id={this.props['data-test-id']}
+                            selectsStart={selectsStart}
+                            selectsEnd={selectsEnd}
+                        />
+                    )}
+                </FormGroup>
+                {this.renderErrorOverlay()}
+            </div>
+        );
+    }
 
-                                       {type === 'radio' &&
-                                       <Radio name={name}
-                                                  checked={checked}
-                                                  disabled={isReadOnlyMode || Boolean(disabled)}
-                                                  value={value}
-                                               onChange={(isChecked)=>this.onChangeRadio(isChecked)}
-                                                  inputRef={(input) => this.input = input}
-                                               label={label}
-                                               data-test-id={this.props['data-test-id']} />}
-                                       {type === 'select' &&
-                                       <FormControl onClick={ (e) => this.optionSelect(e) }
-                                                className='custom-select'
-                                                componentClass={type}
-                                                inputRef={(input) => this.input = input}
-                                                name={name} {...inputProps}
-                                                data-test-id={this.props['data-test-id']}/>}
-                                       {type === 'date' && 
-                                       <Datepicker 
-                                               date={value}
-                                               format={dateFormat}
-                                               startDate={startDate}
-                                               endDate={endDate}
-                                               inputRef={(input) => this.input = input}
-                                               onChange={this.props.onChange}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               data-test-id={this.props['data-test-id']}
-                                               selectsStart={selectsStart}
-                                               selectsEnd={selectsEnd} />}
-                               </FormGroup>
-                               { this.renderErrorOverlay() }
-                       </div>
-               );
-       }
+    getValue() {
+        return this.props.type !== 'select'
+            ? this.state.value
+            : this.state.selectedValues;
+    }
 
-       getValue() {
-               return this.props.type !== 'select' ? this.state.value : this.state.selectedValues;
-       }
+    getChecked() {
+        return this.state.checked;
+    }
 
-       getChecked() {
-               return this.state.checked;
-       }
+    optionSelect(e) {
+        let selectedValues = [];
+        if (e.target.value) {
+            selectedValues.push(e.target.value);
+        }
+        this.setState({
+            selectedValues
+        });
+    }
 
-       optionSelect(e) {
-               let selectedValues = [];
-               if (e.target.value) {
-                       selectedValues.push(e.target.value);
-               }
-               this.setState({
-                       selectedValues
-               });
-       }
+    onChange(e) {
+        const { onChange, type } = this.props;
+        let value = e.target.value;
+        if (type === 'number') {
+            if (value === '') {
+                value = undefined;
+            } else {
+                value = Number(value);
+            }
+        }
+        this.setState({
+            value
+        });
+        onChange(value);
+    }
 
-       onChange(e) {
-               const {onChange, type} = this.props;
-               let value = e.target.value;
-               if (type === 'number') {
-                       if (value === '') {
-                               value = undefined;
-                       } else {
-                               value = Number(value);
-                       }
-               }
-               this.setState({
-                       value
-               });
-               onChange(value);
-       }
+    onChangeCheckBox(e) {
+        let { onChange } = this.props;
+        let checked = e.target.checked;
+        this.setState({
+            checked
+        });
+        onChange(checked);
+    }
 
-       onChangeCheckBox(e) {
-               let {onChange} = this.props;
-               let checked = e.target.checked;
-               this.setState({
-                       checked
-               });
-               onChange(checked);
-       }
+    onChangeRadio(isChecked) {
+        let { onChange } = this.props;
+        this.setState({
+            checked: isChecked
+        });
+        onChange(this.state.value);
+    }
 
-       onChangeRadio(isChecked) {
-               let {onChange} = this.props;
-               this.setState({
-                       checked: isChecked
-               });
-               onChange(this.state.value);
-       }
+    focus() {
+        ReactDOM.findDOMNode(this.input).focus();
+    }
 
-       focus() {
-               ReactDOM.findDOMNode(this.input).focus();
-       }
+    renderErrorOverlay() {
+        let position = 'right';
+        const { errorText = '', isValid = true, type, overlayPos } = this.props;
 
-       renderErrorOverlay() {
-               let position = 'right';
-               const {errorText = '', isValid = true, type, overlayPos} = this.props;
-
-               if (overlayPos) {
-                       position = overlayPos;
-               }
-               else if (type === 'text'
-                       || type === 'email'
-                       || type === 'number'
-                       || type === 'radio'
-                       || type === 'password'
-                       || type === 'date') {
-                       position = 'bottom';
-               }
-
-               return (
-                       <Overlay
-                               show={!isValid}
-                               placement={position}
-                               target={() => {
-                                       let target = ReactDOM.findDOMNode(this.input);
-                                       return target.offsetParent ? target : undefined;
-                               }}
-                               container={this}>
-                               <Tooltip
-                                       id={`error-${errorText.replace(' ', '-')}`}
-                                       className='validation-error-message'>
-                                       {errorText}
-                               </Tooltip>
-                       </Overlay>
-               );
-       }
+        if (overlayPos) {
+            position = overlayPos;
+        } else if (
+            type === 'text' ||
+            type === 'email' ||
+            type === 'number' ||
+            type === 'radio' ||
+            type === 'password' ||
+            type === 'date'
+        ) {
+            position = 'bottom';
+        }
 
+        return (
+            <Overlay
+                show={!isValid}
+                placement={position}
+                target={() => {
+                    let target = ReactDOM.findDOMNode(this.input);
+                    return target.offsetParent ? target : undefined;
+                }}
+                container={this}>
+                <Tooltip
+                    id={`error-${errorText.replace(' ', '-')}`}
+                    className="validation-error-message">
+                    {errorText}
+                </Tooltip>
+            </Overlay>
+        );
+    }
 }
-export default  Input;
+export default Input;
index 11b07ba..019b6a5 100644 (file)
@@ -22,260 +22,341 @@ import Select from 'nfvo-components/input/SelectInput.jsx';
 import Overlay from 'react-bootstrap/lib/Overlay.js';
 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 
-export const other = {OTHER: 'Other'};
+export const other = { OTHER: 'Other' };
 
 class InputOptions extends React.Component {
+    static propTypes = {
+        values: PropTypes.arrayOf(
+            PropTypes.shape({
+                enum: PropTypes.string,
+                title: PropTypes.string
+            })
+        ),
+        isEnabledOther: PropTypes.bool,
+        label: PropTypes.string,
+        selectedValue: PropTypes.string,
+        multiSelectedEnum: PropTypes.oneOfType([
+            PropTypes.string,
+            PropTypes.array
+        ]),
+        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
+    };
 
-       static propTypes = {
-               values: PropTypes.arrayOf(PropTypes.shape({
-                       enum: PropTypes.string,
-                       title: PropTypes.string
-               })),
-               isEnabledOther: PropTypes.bool,
-               label: PropTypes.string,
-               selectedValue: PropTypes.string,
-               multiSelectedEnum: PropTypes.oneOfType([
-                       PropTypes.string,
-                       PropTypes.array
-               ]),
-               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 = {
+        otherInputDisabled: !this.props.otherValue
+    };
 
-       state = {
-               otherInputDisabled: !this.props.otherValue
-       };
+    oldProps = {
+        selectedEnum: '',
+        otherValue: '',
+        multiSelectedEnum: []
+    };
 
-       oldProps = {
-               selectedEnum: '',
-               otherValue: '',
-               multiSelectedEnum: []
-       };
+    render() {
+        let {
+            label,
+            isRequired,
+            values,
+            otherValue,
+            onOtherChange,
+            isMultiSelect,
+            onBlur,
+            multiSelectedEnum,
+            selectedEnum,
+            isValid,
+            children,
+            isReadOnlyMode
+        } = this.props;
+        const dataTestId = this.props['data-test-id']
+            ? { 'data-test-id': this.props['data-test-id'] }
+            : {};
+        let currentMultiSelectedEnum = [];
+        let currentSelectedEnum = '';
+        let otherInputDisabled =
+            (isMultiSelect &&
+                (multiSelectedEnum === undefined ||
+                    multiSelectedEnum.length === 0 ||
+                    multiSelectedEnum[0] !== other.OTHER)) ||
+            (!isMultiSelect &&
+                (selectedEnum === undefined || selectedEnum !== other.OTHER));
+        if (isMultiSelect) {
+            currentMultiSelectedEnum = multiSelectedEnum;
+            if (!otherInputDisabled) {
+                currentSelectedEnum = multiSelectedEnum
+                    ? multiSelectedEnum.toString()
+                    : undefined;
+            }
+        } else if (selectedEnum) {
+            currentSelectedEnum = selectedEnum;
+        }
+        if (!onBlur) {
+            onBlur = () => {};
+        }
 
-       render() {
-               let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, isValid, children, isReadOnlyMode} = this.props;
-               const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
-               let currentMultiSelectedEnum = [];
-               let currentSelectedEnum = '';
-               let otherInputDisabled = (isMultiSelect && (multiSelectedEnum === undefined || multiSelectedEnum.length === 0 || multiSelectedEnum[0] !== other.OTHER))
-                       || (!isMultiSelect && (selectedEnum === undefined || selectedEnum !== other.OTHER));
-               if (isMultiSelect) {
-                       currentMultiSelectedEnum = multiSelectedEnum;
-                       if(!otherInputDisabled) {
-                               currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
-                       }
-               }
-               else if(selectedEnum){
-                       currentSelectedEnum = selectedEnum;
-               }
-               if (!onBlur) {
-                       onBlur = () => {};
-               }
+        return (
+            <div className="validation-input-wrapper">
+                <div
+                    className={classNames('form-group', {
+                        required: isRequired,
+                        'has-error': !isValid
+                    })}>
+                    {label && <label className="control-label">{label}</label>}
+                    {isMultiSelect && otherInputDisabled ? (
+                        <Select
+                            {...dataTestId}
+                            ref={input => (this.input = input)}
+                            value={currentMultiSelectedEnum}
+                            className="options-input"
+                            clearable={false}
+                            required={isRequired}
+                            disabled={
+                                isReadOnlyMode || Boolean(this.props.disabled)
+                            }
+                            onBlur={() => onBlur()}
+                            onMultiSelectChanged={value =>
+                                this.multiSelectEnumChanged(value)
+                            }
+                            options={this.renderMultiSelectOptions(values)}
+                            multi
+                        />
+                    ) : (
+                        <div
+                            className={classNames('input-options', {
+                                'has-error': !isValid
+                            })}>
+                            <select
+                                {...dataTestId}
+                                ref={input => (this.input = input)}
+                                label={label}
+                                className="form-control input-options-select"
+                                value={currentSelectedEnum}
+                                style={{
+                                    width: otherInputDisabled ? '100%' : '100px'
+                                }}
+                                onBlur={() => onBlur()}
+                                disabled={
+                                    isReadOnlyMode ||
+                                    Boolean(this.props.disabled)
+                                }
+                                onChange={value => this.enumChanged(value)}
+                                type="select">
+                                {children ||
+                                    (values &&
+                                        values.length &&
+                                        values.map((val, index) =>
+                                            this.renderOptions(val, index)
+                                        ))}
+                                {onOtherChange && (
+                                    <option key="other" value={other.OTHER}>
+                                        {i18n(other.OTHER)}
+                                    </option>
+                                )}
+                            </select>
 
-               return(
-                       <div className='validation-input-wrapper' >
-                               <div className={classNames('form-group', {'required' : isRequired, 'has-error' : !isValid})} >
-                                       {label && <label className='control-label'>{label}</label>}
-                                       {isMultiSelect && otherInputDisabled ?
-                                               <Select
-                                                       {...dataTestId}
-                                                       ref={(input) => this.input = input}
-                                                       value={currentMultiSelectedEnum}
-                                                       className='options-input'
-                                                       clearable={false}
-                                                       required={isRequired}
-                                                       disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                                       onBlur={() => onBlur()}
-                                                       onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
-                                                       options={this.renderMultiSelectOptions(values)}
-                                                       multi/> :
-                                               <div className={classNames('input-options',{'has-error' : !isValid})} >
-                                                       <select
-                                                               {...dataTestId}
-                                                               ref={(input) => this.input = input}
-                                                               label={label}
-                                                               className='form-control input-options-select'
-                                                               value={currentSelectedEnum}
-                                                               style={{'width' : otherInputDisabled ? '100%' : '100px'}}
-                                                               onBlur={() => onBlur()}
-                                                               disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                                               onChange={ value => this.enumChanged(value)}
-                                                               type='select'>
-                                                               {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
-                                                               {onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
-                                                       </select>
+                            {!otherInputDisabled && (
+                                <div className="input-options-separator" />
+                            )}
+                            <input
+                                className="form-control input-options-other"
+                                placeholder={i18n('other')}
+                                ref={otherValue =>
+                                    (this.otherValue = otherValue)
+                                }
+                                style={{
+                                    display: otherInputDisabled
+                                        ? 'none'
+                                        : 'block'
+                                }}
+                                disabled={
+                                    isReadOnlyMode ||
+                                    Boolean(this.props.disabled)
+                                }
+                                value={otherValue || ''}
+                                onBlur={() => onBlur()}
+                                onChange={() => this.changedOtherInput()}
+                            />
+                        </div>
+                    )}
+                </div>
+                {this.renderErrorOverlay()}
+            </div>
+        );
+    }
 
-                                                       {!otherInputDisabled && <div className='input-options-separator'/>}
-                                                       <input
-                                                               className='form-control input-options-other'
-                                                               placeholder={i18n('other')}
-                                                               ref={(otherValue) => this.otherValue = otherValue}
-                                                               style={{'display' : otherInputDisabled ? 'none' : 'block'}}
-                                                               disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                                               value={otherValue || ''}
-                                                               onBlur={() => onBlur()}
-                                                               onChange={() => this.changedOtherInput()}/>
-                                               </div>
-                                       }
-                                       </div>
-                               { this.renderErrorOverlay() }
-                       </div>
-               );
-       }
+    renderOptions(val, index) {
+        return (
+            <option key={index} value={val.enum}>
+                {val.title}
+            </option>
+        );
+    }
 
-       renderOptions(val, index){
-               return (
-                       <option key={index} value={val.enum}>{val.title}</option>
-               );
-       }
+    renderMultiSelectOptions(values) {
+        let { onOtherChange } = this.props;
+        let optionsList = [];
+        if (onOtherChange) {
+            optionsList = values
+                .map(option => {
+                    return {
+                        label: option.title,
+                        value: option.enum
+                    };
+                })
+                .concat([
+                    {
+                        label: i18n(other.OTHER),
+                        value: i18n(other.OTHER)
+                    }
+                ]);
+        } else {
+            optionsList = values.map(option => {
+                return {
+                    label: option.title,
+                    value: option.enum
+                };
+            });
+        }
+        if (optionsList.length > 0 && optionsList[0].value === '') {
+            optionsList.shift();
+        }
+        return optionsList;
+    }
 
+    renderErrorOverlay() {
+        let position = 'right';
+        const { errorText = '', isValid = true, type, overlayPos } = this.props;
 
-       renderMultiSelectOptions(values) {
-               let {onOtherChange} = this.props;
-               let optionsList = [];
-               if (onOtherChange) {
-                       optionsList = values.map(option => {
-                               return {
-                                       label: option.title,
-                                       value: option.enum,
-                               };
-                       }).concat([{
-                               label: i18n(other.OTHER),
-                               value: i18n(other.OTHER),
-                       }]);
-               }
-               else {
-                       optionsList = values.map(option => {
-                               return {
-                                       label: option.title,
-                                       value: option.enum,
-                               };
-                       });
-               }
-               if (optionsList.length > 0 && optionsList[0].value === '') {
-                       optionsList.shift();
-               }
-               return optionsList;
-       }
+        if (overlayPos) {
+            position = overlayPos;
+        } else if (
+            type === 'text' ||
+            type === 'email' ||
+            type === 'number' ||
+            type === 'password'
+        ) {
+            position = 'bottom';
+        }
 
-       renderErrorOverlay() {
-               let position = 'right';
-               const {errorText = '', isValid = true, type, overlayPos} = this.props;
+        return (
+            <Overlay
+                show={!isValid}
+                placement={position}
+                target={() => {
+                    let { otherInputDisabled } = this.state;
+                    let target = otherInputDisabled
+                        ? ReactDOM.findDOMNode(this.input)
+                        : ReactDOM.findDOMNode(this.otherValue);
+                    return target.offsetParent ? target : undefined;
+                }}
+                container={this}>
+                <Tooltip
+                    id={`error-${errorText.replace(' ', '-')}`}
+                    className="validation-error-message">
+                    {errorText}
+                </Tooltip>
+            </Overlay>
+        );
+    }
 
-               if (overlayPos) {
-                       position = overlayPos;
-               }
-               else if (type === 'text'
-                       || type === 'email'
-                       || type === 'number'
-                       || type === 'password') {
-                       position = 'bottom';
-               }
+    getValue() {
+        let res = '';
+        let { isMultiSelect } = this.props;
+        let { otherInputDisabled } = this.state;
 
-               return (
-                       <Overlay
-                               show={!isValid}
-                               placement={position}
-                               target={() => {
-                                       let {otherInputDisabled} = this.state;
-                                       let target = otherInputDisabled ? ReactDOM.findDOMNode(this.input) :  ReactDOM.findDOMNode(this.otherValue);
-                                       return target.offsetParent ? target : undefined;
-                               }}
-                               container={this}>
-                               <Tooltip
-                                       id={`error-${errorText.replace(' ', '-')}`}
-                                       className='validation-error-message'>
-                                       {errorText}
-                               </Tooltip>
-                       </Overlay>
-               );
-       }
+        if (otherInputDisabled) {
+            res = isMultiSelect ? this.input.getValue() : this.input.value;
+        } else {
+            res = this.otherValue.value;
+        }
+        return res;
+    }
 
-       getValue() {
-               let res = '';
-               let {isMultiSelect} = this.props;
-               let {otherInputDisabled} = this.state;
+    enumChanged() {
+        let enumValue = this.input.value;
+        let {
+            onEnumChange,
+            onOtherChange,
+            isMultiSelect,
+            onChange
+        } = this.props;
+        this.setState({
+            otherInputDisabled:
+                !Boolean(onOtherChange) || enumValue !== other.OTHER
+        });
 
-               if (otherInputDisabled) {
-                       res = isMultiSelect ? this.input.getValue() : this.input.value;
-               } else {
-                       res = this.otherValue.value;
-               }
-               return res;
-       }
+        let value = isMultiSelect ? [enumValue] : enumValue;
+        if (onEnumChange) {
+            onEnumChange(value);
+        }
+        if (onChange) {
+            onChange(value);
+        }
+    }
 
-       enumChanged() {
-               let enumValue = this.input.value;
-               let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
-               this.setState({
-                       otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
-               });
+    multiSelectEnumChanged(enumValue) {
+        let { onEnumChange, onOtherChange } = this.props;
+        let selectedValues = enumValue.map(enumVal => {
+            return enumVal.value;
+        });
 
-               let value = isMultiSelect ? [enumValue] : enumValue;
-               if (onEnumChange) {
-                       onEnumChange(value);
-               }
-               if (onChange) {
-                       onChange(value);
-               }
-       }
+        if (this.state.otherInputDisabled === false) {
+            selectedValues.shift();
+        } else if (selectedValues.includes(i18n(other.OTHER))) {
+            selectedValues = [i18n(other.OTHER)];
+        }
 
-       multiSelectEnumChanged(enumValue) {
-               let {onEnumChange, onOtherChange} = this.props;
-               let selectedValues = enumValue.map(enumVal => {
-                       return enumVal.value;
-               });
+        this.setState({
+            otherInputDisabled:
+                !Boolean(onOtherChange) ||
+                !selectedValues.includes(i18n(other.OTHER))
+        });
+        onEnumChange(selectedValues);
+    }
 
-               if (this.state.otherInputDisabled === false) {
-                       selectedValues.shift();
-               }
-               else if (selectedValues.includes(i18n(other.OTHER))) {
-                       selectedValues = [i18n(other.OTHER)];
-               }
+    changedOtherInput() {
+        let { onOtherChange } = this.props;
+        onOtherChange(this.otherValue.value);
+    }
 
-               this.setState({
-                       otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
-               });
-               onEnumChange(selectedValues);
-       }
-
-       changedOtherInput() {
-               let {onOtherChange} = this.props;
-               onOtherChange(this.otherValue.value);
-       }
-
-       componentDidUpdate() {
-               let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
-               if (this.oldProps.otherValue !== otherValue
-                       || this.oldProps.selectedEnum !== selectedEnum
-                       || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
-                       this.oldProps = {
-                               otherValue,
-                               selectedEnum,
-                               multiSelectedEnum
-                       };
-                       onInputChange();
-               }
-       }
-
-       static getTitleByName(values, name) {
-               for (let key of Object.keys(values)) {
-                       let option = values[key].find(option => option.enum === name);
-                       if (option) {
-                               return option.title;
-                       }
-               }
-               return name;
-       }
+    componentDidUpdate() {
+        let {
+            otherValue,
+            selectedEnum,
+            onInputChange,
+            multiSelectedEnum
+        } = this.props;
+        if (
+            this.oldProps.otherValue !== otherValue ||
+            this.oldProps.selectedEnum !== selectedEnum ||
+            this.oldProps.multiSelectedEnum !== multiSelectedEnum
+        ) {
+            this.oldProps = {
+                otherValue,
+                selectedEnum,
+                multiSelectedEnum
+            };
+            onInputChange();
+        }
+    }
 
+    static getTitleByName(values, name) {
+        for (let key of Object.keys(values)) {
+            let option = values[key].find(option => option.enum === name);
+            if (option) {
+                return option.title;
+            }
+        }
+        return name;
+    }
 }
 
 export default InputOptions;
index e440fcd..3e0bb32 100644 (file)
@@ -22,114 +22,149 @@ import FormGroup from 'react-bootstrap/lib/FormGroup.js';
 import FormControl from 'react-bootstrap/lib/FormControl.js';
 
 class InputWrapper extends React.Component {
-
-       state = {
-               value: this.props.value,
-               checked: this.props.checked,
-               selectedValues: []
-       }
-
-       render() {
-               const {label, hasError, validations = {}, isReadOnlyMode, value, onBlur, onKeyDown, type, disabled, checked, name} = this.props;
-               const {groupClassName, ...inputProps} = this.props;
-               return(
-                       <FormGroup className={classNames('form-group', [groupClassName], {'required' : validations.required , 'has-error' : hasError})} >
-                               {(label && (type !== 'checkbox' && type !== 'radio')) && <label className='control-label'>{label}</label>}
-                               {(type === 'text' || type === 'number') &&
-                                       <FormControl
-                                               bsClass={'form-control input-options-other'}
-                                               onChange={(e) => this.onChange(e)}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               onBlur={onBlur}
-                                               onKeyDown={onKeyDown}
-                                               value={value || ''}
-                                               ref={(input) => this.inputWrapper = input}
-                                               type={type}
-                                               data-test-id={this.props['data-test-id']}/>}
-
-                               {type === 'textarea' &&
-                                       <FormControl
-                                               className='form-control input-options-other'
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               value={value || ''}
-                                               onBlur={onBlur}
-                                               onKeyDown={onKeyDown}
-                                               componentClass={type}
-                                               onChange={(e) => this.onChange(e)}
-                                               data-test-id={this.props['data-test-id']}/>}
-
-                               {type === 'checkbox' &&
-                                       <Checkbox
-                                               className={classNames({'required' : validations.required , 'has-error' : hasError})}
-                                               onChange={(e)=>this.onChangeCheckBox(e)}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               checked={value}
-                                               data-test-id={this.props['data-test-id']}>{label}</Checkbox>}
-
-                               {type === 'radio' &&
-                                       <Radio name={name}
-                                               checked={checked}
-                                               disabled={isReadOnlyMode || Boolean(disabled)}
-                                               value={value}
-                                               ref={(input) => this.inputWrapper = input}
-                                               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}
-                                               name={name} {...inputProps}
-                                               data-test-id={this.props['data-test-id']}/>}
-
-                       </FormGroup>
-
-               );
-       }
-
-       getValue() {
-               return this.props.type !== 'select' ? this.state.value : this.state.selectedValues;
-       }
-
-       getChecked() {
-               return this.state.checked;
-       }
-
-       optionSelect(e) {
-               let selectedValues = [];
-               if (e.target.value) {
-                       selectedValues.push(e.target.value);
-               }
-               this.setState({
-                       selectedValues
-               });
-       }
-
-       onChange(e) {
-               let {onChange} = this.props;
-               this.setState({
-                       value: e.target.value
-               });
-               onChange(e.target.value);
-       }
-
-       onChangeCheckBox(e) {
-               let {onChange} = this.props;
-               this.setState({
-                       checked: e.target.checked
-               });
-               onChange(e.target.checked);
-       }
-
-       onChangeRadio(isChecked) {
-               let {onChange} = this.props;
-               this.setState({
-                       checked: isChecked
-               });
-               onChange(this.state.value);
-       }
-
-       focus() {
-               ReactDOM.findDOMNode(this.inputWrapper).focus();
-       }
-
+    state = {
+        value: this.props.value,
+        checked: this.props.checked,
+        selectedValues: []
+    };
+
+    render() {
+        const {
+            label,
+            hasError,
+            validations = {},
+            isReadOnlyMode,
+            value,
+            onBlur,
+            onKeyDown,
+            type,
+            disabled,
+            checked,
+            name
+        } = this.props;
+        const { groupClassName, ...inputProps } = this.props;
+        return (
+            <FormGroup
+                className={classNames('form-group', [groupClassName], {
+                    required: validations.required,
+                    'has-error': hasError
+                })}>
+                {label &&
+                    (type !== 'checkbox' && type !== 'radio') && (
+                        <label className="control-label">{label}</label>
+                    )}
+                {(type === 'text' || type === 'number') && (
+                    <FormControl
+                        bsClass={'form-control input-options-other'}
+                        onChange={e => this.onChange(e)}
+                        disabled={isReadOnlyMode || Boolean(disabled)}
+                        onBlur={onBlur}
+                        onKeyDown={onKeyDown}
+                        value={value || ''}
+                        ref={input => (this.inputWrapper = input)}
+                        type={type}
+                        data-test-id={this.props['data-test-id']}
+                    />
+                )}
+
+                {type === 'textarea' && (
+                    <FormControl
+                        className="form-control input-options-other"
+                        disabled={isReadOnlyMode || Boolean(disabled)}
+                        value={value || ''}
+                        onBlur={onBlur}
+                        onKeyDown={onKeyDown}
+                        componentClass={type}
+                        onChange={e => this.onChange(e)}
+                        data-test-id={this.props['data-test-id']}
+                    />
+                )}
+
+                {type === 'checkbox' && (
+                    <Checkbox
+                        className={classNames({
+                            required: validations.required,
+                            'has-error': hasError
+                        })}
+                        onChange={e => this.onChangeCheckBox(e)}
+                        disabled={isReadOnlyMode || Boolean(disabled)}
+                        checked={value}
+                        data-test-id={this.props['data-test-id']}>
+                        {label}
+                    </Checkbox>
+                )}
+
+                {type === 'radio' && (
+                    <Radio
+                        name={name}
+                        checked={checked}
+                        disabled={isReadOnlyMode || Boolean(disabled)}
+                        value={value}
+                        ref={input => (this.inputWrapper = input)}
+                        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}
+                        name={name}
+                        {...inputProps}
+                        data-test-id={this.props['data-test-id']}
+                    />
+                )}
+            </FormGroup>
+        );
+    }
+
+    getValue() {
+        return this.props.type !== 'select'
+            ? this.state.value
+            : this.state.selectedValues;
+    }
+
+    getChecked() {
+        return this.state.checked;
+    }
+
+    optionSelect(e) {
+        let selectedValues = [];
+        if (e.target.value) {
+            selectedValues.push(e.target.value);
+        }
+        this.setState({
+            selectedValues
+        });
+    }
+
+    onChange(e) {
+        let { onChange } = this.props;
+        this.setState({
+            value: e.target.value
+        });
+        onChange(e.target.value);
+    }
+
+    onChangeCheckBox(e) {
+        let { onChange } = this.props;
+        this.setState({
+            checked: e.target.checked
+        });
+        onChange(e.target.checked);
+    }
+
+    onChangeRadio(isChecked) {
+        let { onChange } = this.props;
+        this.setState({
+            checked: isChecked
+        });
+        onChange(this.state.value);
+    }
+
+    focus() {
+        ReactDOM.findDOMNode(this.inputWrapper).focus();
+    }
 }
-export default  InputWrapper;
+export default InputWrapper;
index 0982c13..429985a 100644 (file)
 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 { default as SDCTabs } from 'sdc-ui/lib/react/Tabs.js';
 import Overlay from 'react-bootstrap/lib/Overlay.js';
 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-export default
-class Tabs extends React.Component {
+export default class Tabs extends React.Component {
+    static propTypes = {
+        children: PropTypes.node
+    };
 
-       static propTypes = {
-               children: PropTypes.node
-       };
+    cloneTab(element) {
+        const { invalidTabs } = this.props;
+        return React.cloneElement(element, {
+            key: element.props.tabId,
+            className:
+                invalidTabs.indexOf(element.props.tabId) > -1
+                    ? 'invalid-tab'
+                    : 'valid-tab'
+        });
+    }
 
-       cloneTab(element) {
-               const {invalidTabs} = this.props;
-               return React.cloneElement(
-                       element,
-                       {
-                               key: element.props.tabId,
-                               className: invalidTabs.indexOf(element.props.tabId) > -1 ? 'invalid-tab' : 'valid-tab'
-                       }
-               );
-       }
+    showTabsError() {
+        const { invalidTabs } = this.props;
+        const showError =
+            (invalidTabs.length === 1 &&
+                invalidTabs[0] !== this.props.activeTab) ||
+            invalidTabs.length > 1;
+        return showError;
+    }
 
-       showTabsError() {
-               const {invalidTabs} = this.props;
-               const showError = ((invalidTabs.length === 1 && invalidTabs[0] !== this.props.activeTab) || (invalidTabs.length > 1));
-               return showError;
-       }
-
-       render() {
-               // eslint-disable-next-line no-unused-vars
-               let {invalidTabs, ...tabProps} = this.props;
-               return (
-                       <div>
-                               <SDCTabs {...tabProps} ref='tabsList' id='tabsList' >
-                                       {this.props.children.map(element => this.cloneTab(element))}
-                               </SDCTabs>
-                               <Overlay
-                                       animation={false}
-                                       show={this.showTabsError()}
-                                       placement='bottom'
-                                       target={() => {
-                                               let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)');
-                                               return target && target.offsetParent ? target : undefined;
-                                       }
-                                       }
-                                       container={() => {
-                                               let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)');
-                                               return target && target.offsetParent ? target.offsetParent : this;
-                                       }}>
-                                       <Tooltip
-                                               id='error-some-tabs-contain-errors'
-                                               className='validation-error-message'>
-                                               {i18n('One or more tabs are invalid')}
-                                       </Tooltip>
-                               </Overlay>
-                       </div>
-               );
-       }
+    render() {
+        // eslint-disable-next-line no-unused-vars
+        let { invalidTabs, ...tabProps } = this.props;
+        return (
+            <div>
+                <SDCTabs {...tabProps} ref="tabsList" id="tabsList">
+                    {this.props.children.map(element => this.cloneTab(element))}
+                </SDCTabs>
+                <Overlay
+                    animation={false}
+                    show={this.showTabsError()}
+                    placement="bottom"
+                    target={() => {
+                        let target = ReactDOM.findDOMNode(
+                            this.refs.tabsList
+                        ).querySelector(
+                            'ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)'
+                        );
+                        return target && target.offsetParent
+                            ? target
+                            : undefined;
+                    }}
+                    container={() => {
+                        let target = ReactDOM.findDOMNode(
+                            this.refs.tabsList
+                        ).querySelector(
+                            'ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)'
+                        );
+                        return target && target.offsetParent
+                            ? target.offsetParent
+                            : this;
+                    }}>
+                    <Tooltip
+                        id="error-some-tabs-contain-errors"
+                        className="validation-error-message">
+                        {i18n('One or more tabs are invalid')}
+                    </Tooltip>
+                </Overlay>
+            </div>
+        );
+    }
 }
index 151d3fe..e460f68 100644 (file)
@@ -27,32 +27,63 @@ import Button from 'sdc-ui/lib/react/Button.js';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 
 class ValidationButtons extends React.Component {
+    static propTypes = {
+        labledButtons: PropTypes.bool.isRequired,
+        isReadOnlyMode: PropTypes.bool,
+        submitButtonText: PropTypes.string,
+        cancelButtonText: PropTypes.string
+    };
 
-       static propTypes = {
-               labledButtons: PropTypes.bool.isRequired,
-               isReadOnlyMode: PropTypes.bool,
-               submitButtonText: PropTypes.string,
-               cancelButtonText: PropTypes.string
-       };
+    state = {
+        isValid: this.props.formValid
+    };
 
-       state = {
-               isValid: this.props.formValid
-       };
-
-       render() {
-               let submitBtn = this.props.labledButtons ? this.props.submitButtonText ? this.props.submitButtonText : i18n('Save') : <SVGIcon className='check' name='check'/>;
-               let closeBtn = this.props.labledButtons ? this.props.cancelButtonText ? this.props.cancelButtonText : i18n('Cancel') : <SVGIcon className='close' name='close'/>;
-               return (
-                       <div className='validation-buttons'>
-                               {!this.props.isReadOnlyMode ?
-                                       <div>
-                                               <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' data-test-id='form-close-button'>{i18n('Close')}</Button>
-                               }
-                       </div>
-               );
-       }
+    render() {
+        let submitBtn = this.props.labledButtons ? (
+            this.props.submitButtonText ? (
+                this.props.submitButtonText
+            ) : (
+                i18n('Save')
+            )
+        ) : (
+            <SVGIcon className="check" name="check" />
+        );
+        let closeBtn = this.props.labledButtons ? (
+            this.props.cancelButtonText ? (
+                this.props.cancelButtonText
+            ) : (
+                i18n('Cancel')
+            )
+        ) : (
+            <SVGIcon className="close" name="close" />
+        );
+        return (
+            <div className="validation-buttons">
+                {!this.props.isReadOnlyMode ? (
+                    <div>
+                        <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"
+                        data-test-id="form-close-button">
+                        {i18n('Close')}
+                    </Button>
+                )}
+            </div>
+        );
+    }
 }
 export default ValidationButtons;
index 60c559a..359af9d 100644 (file)
@@ -19,50 +19,78 @@ import classnames from 'classnames';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import store from 'sdc-app/AppStore.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 class ListEditorItem extends React.Component {
-       static propTypes = {
-               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
-       };
+    static propTypes = {
+        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() {
-               let {onDelete, onSelect, onEdit, children, isReadOnlyMode} = this.props;
-               let isAbilityToDelete = isReadOnlyMode === undefined ? true : !isReadOnlyMode;
-               return (
-                       <div className={classnames('list-editor-item-view', {'selectable': Boolean(onSelect)})} data-test-id='list-editor-item'>
-                               <div className='list-editor-item-view-content' onClick={onSelect}>
-                                       {children}
-                               </div>
-                               {(onEdit || onDelete) && <div className='list-editor-item-view-controller'>
-                                       {onEdit && <SVGIcon name='sliders' onClick={() => this.onClickedItem(onEdit)}/>}
-                                       {onDelete && isAbilityToDelete && <SVGIcon name='trashO' data-test-id='delete-list-item' onClick={() => this.onClickedItem(onDelete)}/>}
-                               </div>}
-                       </div>
-               );
-       }
+    render() {
+        let {
+            onDelete,
+            onSelect,
+            onEdit,
+            children,
+            isReadOnlyMode
+        } = this.props;
+        let isAbilityToDelete =
+            isReadOnlyMode === undefined ? true : !isReadOnlyMode;
+        return (
+            <div
+                className={classnames('list-editor-item-view', {
+                    selectable: Boolean(onSelect)
+                })}
+                data-test-id="list-editor-item">
+                <div
+                    className="list-editor-item-view-content"
+                    onClick={onSelect}>
+                    {children}
+                </div>
+                {(onEdit || onDelete) && (
+                    <div className="list-editor-item-view-controller">
+                        {onEdit && (
+                            <SVGIcon
+                                name="sliders"
+                                onClick={() => this.onClickedItem(onEdit)}
+                            />
+                        )}
+                        {onDelete &&
+                            isAbilityToDelete && (
+                                <SVGIcon
+                                    name="trashO"
+                                    data-test-id="delete-list-item"
+                                    onClick={() => this.onClickedItem(onDelete)}
+                                />
+                            )}
+                    </div>
+                )}
+            </div>
+        );
+    }
 
-       onClickedItem(callBackFunc) {
-               if(typeof callBackFunc === 'function') {
-                       let {isCheckedOut} = this.props;
-                       if (isCheckedOut === false) {
-                               store.dispatch({
-                                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                                       data: {
-                                               title: i18n('Error'),
-                                               msg: i18n('This item is checkedin/submitted, Click Check Out to continue')
-                                       }
-                               });
-                       }
-                       else {
-                               callBackFunc();
-                       }
-               }
-       }
+    onClickedItem(callBackFunc) {
+        if (typeof callBackFunc === 'function') {
+            let { isCheckedOut } = this.props;
+            if (isCheckedOut === false) {
+                store.dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                    data: {
+                        title: i18n('Error'),
+                        msg: i18n(
+                            'This item is checkedin/submitted, Click Check Out to continue'
+                        )
+                    }
+                });
+            } else {
+                callBackFunc();
+            }
+        }
+    }
 }
 
 export default ListEditorItem;
index 839f9a5..509ea17 100644 (file)
  */
 import React from 'react';
 
-export const ListEditorItemViewField = ({children}) => (
-       <div className='list-editor-item-view-field'>
-               {children}
-       </div>
+export const ListEditorItemViewField = ({ children }) => (
+    <div className="list-editor-item-view-field">{children}</div>
 );
 
 export default ListEditorItemViewField;
index 16823b7..f71372c 100644 (file)
@@ -19,69 +19,107 @@ import Button from 'sdc-ui/lib/react/Button.js';
 import classnames from 'classnames';
 import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
 
-const ListEditorHeader = ({onAdd, isReadOnlyMode, title, plusButtonTitle}) => {
-        return (
-                <div className='list-editor-view-header'>
-                        {title && <div className='list-editor-view-title'>{title}</div>}
-                        <div>
-                                { onAdd &&
-                                        <Button data-test-id='add-button' iconName='plusThin' btnType='link' onClick={onAdd} disabled={isReadOnlyMode === true}>{plusButtonTitle}</Button>
-                                }
-                        </div>
-                </div>
-        );
+const ListEditorHeader = ({
+    onAdd,
+    isReadOnlyMode,
+    title,
+    plusButtonTitle
+}) => {
+    return (
+        <div className="list-editor-view-header">
+            {title && <div className="list-editor-view-title">{title}</div>}
+            <div>
+                {onAdd && (
+                    <Button
+                        data-test-id="add-button"
+                        iconName="plusThin"
+                        btnType="link"
+                        onClick={onAdd}
+                        disabled={isReadOnlyMode === true}>
+                        {plusButtonTitle}
+                    </Button>
+                )}
+            </div>
+        </div>
+    );
 };
 
-const ListEditorScroller = ({children, twoColumns}) => {
-       return (
-               <div className='list-editor-view-list-scroller'>
-                       <div className={classnames('list-editor-view-list', {'two-columns': twoColumns})}>
-                               {children}
-                       </div>
-               </div>
-       );
+const ListEditorScroller = ({ children, twoColumns }) => {
+    return (
+        <div className="list-editor-view-list-scroller">
+            <div
+                className={classnames('list-editor-view-list', {
+                    'two-columns': twoColumns
+                })}>
+                {children}
+            </div>
+        </div>
+    );
 };
 
-const FilterWrapper = ({onFilter, filterValue}) => {
-       return (
-               <div className='expandble-search-wrapper'>
-                       <ExpandableInput
-                               onChange={onFilter}
-                               iconType='search'
-                               value={filterValue}/>
-               </div>
-       );
+const FilterWrapper = ({ onFilter, filterValue }) => {
+    return (
+        <div className="expandble-search-wrapper">
+            <ExpandableInput
+                onChange={onFilter}
+                iconType="search"
+                value={filterValue}
+            />
+        </div>
+    );
 };
 
 class ListEditorView extends React.Component {
+    static defaultProps = {
+        className: '',
+        twoColumns: false
+    };
 
-       static defaultProps = {
-               className: '',
-               twoColumns: false
-       };
-
-       static propTypes = {
-               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() {
-               let {title, plusButtonTitle, onAdd, children, onFilter, className, isReadOnlyMode, twoColumns, filterValue} = this.props;
-               return (
-                       <div className={classnames('list-editor-view', className)}>
-                               <ListEditorHeader onAdd={onAdd} isReadOnlyMode={isReadOnlyMode} plusButtonTitle={plusButtonTitle} title={title}/>
-                               {onFilter && (children.length || filterValue) && <FilterWrapper onFilter={onFilter} filterValue={filterValue}/>}
-                               <ListEditorScroller children={children} twoColumns={twoColumns}/>
-                       </div>
-               );
-       }
+    static propTypes = {
+        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() {
+        let {
+            title,
+            plusButtonTitle,
+            onAdd,
+            children,
+            onFilter,
+            className,
+            isReadOnlyMode,
+            twoColumns,
+            filterValue
+        } = this.props;
+        return (
+            <div className={classnames('list-editor-view', className)}>
+                <ListEditorHeader
+                    onAdd={onAdd}
+                    isReadOnlyMode={isReadOnlyMode}
+                    plusButtonTitle={plusButtonTitle}
+                    title={title}
+                />
+                {onFilter &&
+                    (children.length || filterValue) && (
+                        <FilterWrapper
+                            onFilter={onFilter}
+                            filterValue={filterValue}
+                        />
+                    )}
+                <ListEditorScroller
+                    children={children}
+                    twoColumns={twoColumns}
+                />
+            </div>
+        );
+    }
 }
 export default ListEditorView;
index 81125c8..67258c9 100644 (file)
@@ -1,27 +1,25 @@
 import React from 'react';
-import {storiesOf, action} from '@kadira/storybook';
+import { storiesOf, action } from '@kadira/storybook';
 import ListEditorView from './ListEditorView.jsx';
 import ListEditorItemView from './ListEditorItemView.jsx';
 import ListEditorItemField from './ListEditorItemViewField.jsx';
-import {text, number} from '@kadira/storybook-addon-knobs';
-import {withKnobs} from '@kadira/storybook-addon-knobs';
+import { text, number } from '@kadira/storybook-addon-knobs';
+import { withKnobs } from '@kadira/storybook-addon-knobs';
 
-function makeChildren({onEdit = false, onDelete = false} = {}) {
-    return (
-        [...Array(number('Items', 2)).keys()].map(index => (
-            <ListEditorItemView 
-                key={index} 
-                onEdit={onEdit ? onEdit : undefined}
-                onDelete={onDelete ? onDelete : undefined}>
-                               <ListEditorItemField>
-                    <div>{text('field 1', 'Lorum Ipsum')}</div>
-                               </ListEditorItemField>
-                               <ListEditorItemField>
-                    <div>{text('field 2', 'Lorum Ipsum')}</div>
-                               </ListEditorItemField>
-            </ListEditorItemView>)
-        )
-    );
+function makeChildren({ onEdit = false, onDelete = false } = {}) {
+    return [...Array(number('Items', 2)).keys()].map(index => (
+        <ListEditorItemView
+            key={index}
+            onEdit={onEdit ? onEdit : undefined}
+            onDelete={onDelete ? onDelete : undefined}>
+            <ListEditorItemField>
+                <div>{text('field 1', 'Lorum Ipsum')}</div>
+            </ListEditorItemField>
+            <ListEditorItemField>
+                <div>{text('field 2', 'Lorum Ipsum')}</div>
+            </ListEditorItemField>
+        </ListEditorItemView>
+    ));
 }
 
 const stories = storiesOf('ListEditor', module);
@@ -29,32 +27,49 @@ stories.addDecorator(withKnobs);
 
 stories
     .add('regular', () => (
-        <ListEditorView title='List Editor'>
-        {makeChildren()}
-        </ListEditorView>
+        <ListEditorView title="List Editor">{makeChildren()}</ListEditorView>
     ))
     .add('two columns', () => (
-        <ListEditorView title='List Editor' twoColumns>
+        <ListEditorView title="List Editor" twoColumns>
             {makeChildren()}
         </ListEditorView>
     ))
     .add('with add', () => (
-        <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
-        {makeChildren()}
+        <ListEditorView
+            title="List Editor"
+            onAdd={action('onAdd')}
+            plusButtonTitle="Add"
+            twoColumns>
+            {makeChildren()}
         </ListEditorView>
     ))
     .add('with delete', () => (
-        <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
-        {makeChildren({onDelete: action('onDelete')})}
+        <ListEditorView
+            title="List Editor"
+            onAdd={action('onAdd')}
+            plusButtonTitle="Add"
+            twoColumns>
+            {makeChildren({ onDelete: action('onDelete') })}
         </ListEditorView>
     ))
     .add('with edit', () => (
-        <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
-        {makeChildren({onEdit: action('onEdit')})}
+        <ListEditorView
+            title="List Editor"
+            onAdd={action('onAdd')}
+            plusButtonTitle="Add"
+            twoColumns>
+            {makeChildren({ onEdit: action('onEdit') })}
         </ListEditorView>
     ))
     .add('with edit and delete', () => (
-        <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
-        {makeChildren({onDelete: action('onDelete'), onEdit: action('onEdit')})}
+        <ListEditorView
+            title="List Editor"
+            onAdd={action('onAdd')}
+            plusButtonTitle="Add"
+            twoColumns>
+            {makeChildren({
+                onDelete: action('onDelete'),
+                onEdit: action('onEdit')
+            })}
         </ListEditorView>
     ));
index 9ebe52d..076351b 100644 (file)
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
-const mapStateToProps = ({loader}) => {
-       return {
-               isLoading: loader.isLoading
-       };
+const mapStateToProps = ({ loader }) => {
+    return {
+        isLoading: loader.isLoading
+    };
 };
 
 class Loader extends React.Component {
-
-       static propTypes = {
-               isLoading: PropTypes.bool.isRequired
-       };
-
-       static defaultProps = {
-               isLoading: false
-       };
-
-       shouldComponentUpdate(nextProps) {
-               return (nextProps.isLoading !== this.props.isLoading);
-       }
-
-       render() {
-               let {isLoading} = this.props;
-               return (
-                       <div className='onboarding-loader'>
-                               {
-                                       isLoading && <div className='onboarding-loader-backdrop'>
-                                               <div className='tlv-loader large'></div>
-                                       </div>
-                               }
-                       </div>
-               );
-       }
+    static propTypes = {
+        isLoading: PropTypes.bool.isRequired
+    };
+
+    static defaultProps = {
+        isLoading: false
+    };
+
+    shouldComponentUpdate(nextProps) {
+        return nextProps.isLoading !== this.props.isLoading;
+    }
+
+    render() {
+        let { isLoading } = this.props;
+        return (
+            <div className="onboarding-loader">
+                {isLoading && (
+                    <div className="onboarding-loader-backdrop">
+                        <div className="tlv-loader large" />
+                    </div>
+                )}
+            </div>
+        );
+    }
 }
 
-export default connect(mapStateToProps) (Loader);
+export default connect(mapStateToProps)(Loader);
index 2b531b0..e367a74 100644 (file)
@@ -16,9 +16,9 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       SHOW: null,
-       HIDE: null,
+    SHOW: null,
+    HIDE: null,
 
-       SEND_REQUEST:  null,
-       RECEIVE_RESPONSE: null
+    SEND_REQUEST: null,
+    RECEIVE_RESPONSE: null
 });
index 3afdad0..1d0f679 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {actionTypes} from './LoaderConstants.js';
+import { actionTypes } from './LoaderConstants.js';
 
-export default (state = {fetchingRequests : 0, currentlyFetching : [],  isLoading : false}, action) => {
-       let fetchingRequests = state.fetchingRequests;
-       let newArray;
-       switch (action.type) {
-               case actionTypes.SEND_REQUEST:
-                       fetchingRequests++;
-                       newArray = state.currentlyFetching.slice();
-                       newArray.splice(0, 0, action.url);
-                       if (DEBUG) {
-                               console.log('Loader SEND REQUEST url: ' + action.url);
-                               console.log('Loader SEND REQUEST number of fetching requests: ' + fetchingRequests);
-                       }
-                       return {
-                               fetchingRequests: fetchingRequests,
-                               currentlyFetching : newArray,
-                               isLoading: true
-                       };
-               case actionTypes.RECEIVE_RESPONSE:
-                       fetchingRequests--;
+export default (
+    state = { fetchingRequests: 0, currentlyFetching: [], isLoading: false },
+    action
+) => {
+    let fetchingRequests = state.fetchingRequests;
+    let newArray;
+    switch (action.type) {
+        case actionTypes.SEND_REQUEST:
+            fetchingRequests++;
+            newArray = state.currentlyFetching.slice();
+            newArray.splice(0, 0, action.url);
+            if (DEBUG) {
+                console.log('Loader SEND REQUEST url: ' + action.url);
+                console.log(
+                    'Loader SEND REQUEST number of fetching requests: ' +
+                        fetchingRequests
+                );
+            }
+            return {
+                fetchingRequests: fetchingRequests,
+                currentlyFetching: newArray,
+                isLoading: true
+            };
+        case actionTypes.RECEIVE_RESPONSE:
+            fetchingRequests--;
 
-                       newArray = state.currentlyFetching.filter((item) => {return item !== action.url;});
-                       if (DEBUG) {
-                               console.log('Loader RECEIVE_RESPONSE url: ' + action.url);
-                               console.log('Loader RECEIVE_RESPONSE: number of fetching requests: ' + fetchingRequests);
-                       }
-                       return {
-                               currentlyFetching : newArray,
-                               fetchingRequests: fetchingRequests,
-                               isLoading: (fetchingRequests !== 0)
-                       };
-               case actionTypes.SHOW:
-                       return {isLoading: true};
-               case actionTypes.HIDE:
-                       return {isLoading: false};
-               default:
-                       return state;
-       }
+            newArray = state.currentlyFetching.filter(item => {
+                return item !== action.url;
+            });
+            if (DEBUG) {
+                console.log('Loader RECEIVE_RESPONSE url: ' + action.url);
+                console.log(
+                    'Loader RECEIVE_RESPONSE: number of fetching requests: ' +
+                        fetchingRequests
+                );
+            }
+            return {
+                currentlyFetching: newArray,
+                fetchingRequests: fetchingRequests,
+                isLoading: fetchingRequests !== 0
+            };
+        case actionTypes.SHOW:
+            return { isLoading: true };
+        case actionTypes.HIDE:
+            return { isLoading: false };
+        default:
+            return state;
+    }
 };
index 75b7983..3f19bd7 100644 (file)
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import Modal from 'nfvo-components/modal/Modal.jsx';
 import Button from 'sdc-ui/lib/react/Button.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {modalContentComponents} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes, typeEnum} from './GlobalModalConstants.js';
-
+import { modalContentComponents } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes, typeEnum } from './GlobalModalConstants.js';
 
 const typeClass = {
-       'default': 'primary',
-       error: 'negative',
-       warning: 'warning',
-       success: 'positive'
+    default: 'primary',
+    error: 'negative',
+    warning: 'warning',
+    success: 'positive'
 };
 
 const type2HeaderColor = {
-       'default': 'primary',
-       error: 'danger',
-       warning: 'warning',
-       success: 'success'
+    default: 'primary',
+    error: 'danger',
+    warning: 'warning',
+    success: 'success'
 };
 
-
-const ModalFooter = ({type, onConfirmed, onDeclined, onClose, confirmationButtonText, cancelButtonText}) => {
-       let myPropsForNoConfirmed = {};
-       if (onConfirmed) {
-               myPropsForNoConfirmed.btnType = 'outline';
-       }
-       return (
-               <Modal.Footer>
-                       <div className='sdc-modal-footer'>
-                               {onConfirmed && <Button data-test-id='sdc-modal-confirm-button' color={typeClass[type]} onClick={() => {
-                                       onConfirmed();
-                                       onClose();
-                               }}>{confirmationButtonText}</Button>}
-                               <Button {...myPropsForNoConfirmed} data-test-id='sdc-modal-cancel-button' btnType='outline' color={typeClass[type]} onClick={onDeclined ? () => {
-                                       onDeclined();
-                                       onClose();} : () => onClose()}>
-                                       {cancelButtonText}
-                               </Button>
-                       </div>
-               </Modal.Footer>
-       );
+const ModalFooter = ({
+    type,
+    onConfirmed,
+    onDeclined,
+    onClose,
+    confirmationButtonText,
+    cancelButtonText
+}) => {
+    let myPropsForNoConfirmed = {};
+    if (onConfirmed) {
+        myPropsForNoConfirmed.btnType = 'outline';
+    }
+    return (
+        <Modal.Footer>
+            <div className="sdc-modal-footer">
+                {onConfirmed && (
+                    <Button
+                        data-test-id="sdc-modal-confirm-button"
+                        color={typeClass[type]}
+                        onClick={() => {
+                            onConfirmed();
+                            onClose();
+                        }}>
+                        {confirmationButtonText}
+                    </Button>
+                )}
+                <Button
+                    {...myPropsForNoConfirmed}
+                    data-test-id="sdc-modal-cancel-button"
+                    btnType="outline"
+                    color={typeClass[type]}
+                    onClick={
+                        onDeclined
+                            ? () => {
+                                  onDeclined();
+                                  onClose();
+                              }
+                            : () => onClose()
+                    }>
+                    {cancelButtonText}
+                </Button>
+            </div>
+        </Modal.Footer>
+    );
 };
 
 ModalFooter.defaultProps = {
-       type: 'default',
-       confirmationButtonText: i18n('OK'),
-       cancelButtonText: i18n('Cancel')
+    type: 'default',
+    confirmationButtonText: i18n('OK'),
+    cancelButtonText: i18n('Cancel')
 };
 
 ModalFooter.PropTypes = {
-       type: PropTypes.string,
-       confirmationButtonText: PropTypes.string,
-       cancelButtonText: PropTypes.string
+    type: PropTypes.string,
+    confirmationButtonText: PropTypes.string,
+    cancelButtonText: PropTypes.string
 };
 
-export const mapStateToProps = ({modal}) => {
-       const show = !!modal;
-       return {
-               show,
-               ...modal
-       };
+export const mapStateToProps = ({ modal }) => {
+    const show = !!modal;
+    return {
+        show,
+        ...modal
+    };
 };
 
-export const mapActionToProps = (dispatch) => {
-       return {
-               onClose:  () => dispatch({type: actionTypes.GLOBAL_MODAL_CLOSE})
-       };
+export const mapActionToProps = dispatch => {
+    return {
+        onClose: () => dispatch({ type: actionTypes.GLOBAL_MODAL_CLOSE })
+    };
 };
 
-
-export class  GlobalModalView extends React.Component {
-
-       static propTypes = {
-               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 = {
-               show: false,
-               type: 'default',
-               title: ''
-       };
-
-       render() {
-               let {title, type, show, modalComponentName, modalComponentProps,
-               modalClassName, msg, onConfirmed, onDeclined, confirmationButtonText, cancelButtonText, onClose} = this.props;
-               const  ComponentToRender = modalContentComponents[modalComponentName];
-               return (
-                       <Modal show={show} bsSize={modalComponentProps && modalComponentProps.size} className={`onborading-modal ${modalClassName || ''} ${type2HeaderColor[type]}`}>
-                               <Modal.Header>
-                                       <Modal.Title>{title}</Modal.Title>
-                               </Modal.Header>
-                               <Modal.Body>
-                                       {ComponentToRender ?
-                                               <ComponentToRender {...modalComponentProps}/> :
-                                               msg && typeof msg === 'string' ?
-                                                       <div> {msg.split('\n').map((txt, i) => <span key={i}> {txt} <br/> </span>)} </div> :
-                                                       msg
-                                       }
-                               </Modal.Body>
-                               {(onConfirmed || onDeclined || type !== typeEnum.DEFAULT) &&
-                                               <ModalFooter
-                                                       type={type}
-                                                       onConfirmed={onConfirmed}
-                                                       onDeclined={onDeclined}
-                                                       onClose={onClose}
-                                                       confirmationButtonText={confirmationButtonText}
-                                                       cancelButtonText={cancelButtonText}/>}
-                       </Modal>
-               );
-       }
-
-       componentDidUpdate() {
-               if (this.props.timeout) {
-                       setTimeout(this.props.onClose, this.props.timeout);
-               }
-       }
-};
+export class GlobalModalView extends React.Component {
+    static propTypes = {
+        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 = {
+        show: false,
+        type: 'default',
+        title: ''
+    };
+
+    render() {
+        let {
+            title,
+            type,
+            show,
+            modalComponentName,
+            modalComponentProps,
+            modalClassName,
+            msg,
+            onConfirmed,
+            onDeclined,
+            confirmationButtonText,
+            cancelButtonText,
+            onClose
+        } = this.props;
+        const ComponentToRender = modalContentComponents[modalComponentName];
+        return (
+            <Modal
+                show={show}
+                bsSize={modalComponentProps && modalComponentProps.size}
+                className={`onborading-modal ${modalClassName || ''} ${
+                    type2HeaderColor[type]
+                }`}>
+                <Modal.Header>
+                    <Modal.Title>{title}</Modal.Title>
+                </Modal.Header>
+                <Modal.Body>
+                    {ComponentToRender ? (
+                        <ComponentToRender {...modalComponentProps} />
+                    ) : msg && typeof msg === 'string' ? (
+                        <div>
+                            {' '}
+                            {msg.split('\n').map((txt, i) => (
+                                <span key={i}>
+                                    {' '}
+                                    {txt} <br />{' '}
+                                </span>
+                            ))}{' '}
+                        </div>
+                    ) : (
+                        msg
+                    )}
+                </Modal.Body>
+                {(onConfirmed || onDeclined || type !== typeEnum.DEFAULT) && (
+                    <ModalFooter
+                        type={type}
+                        onConfirmed={onConfirmed}
+                        onDeclined={onDeclined}
+                        onClose={onClose}
+                        confirmationButtonText={confirmationButtonText}
+                        cancelButtonText={cancelButtonText}
+                    />
+                )}
+            </Modal>
+        );
+    }
+
+    componentDidUpdate() {
+        if (this.props.timeout) {
+            setTimeout(this.props.onClose, this.props.timeout);
+        }
+    }
+}
 
 GlobalModalView.propTypes = {
-       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
+    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
 };
 
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(GlobalModalView);
+export default connect(mapStateToProps, mapActionToProps, null, {
+    withRef: true
+})(GlobalModalView);
index 3e55453..e9c1853 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       GLOBAL_MODAL_SHOW: null,
-       GLOBAL_MODAL_CLOSE: null,
-       GLOBAL_MODAL_ERROR: null,
-       GLOBAL_MODAL_WARNING: null,
-       GLOBAL_MODAL_SUCCESS: null,
-
+    GLOBAL_MODAL_SHOW: null,
+    GLOBAL_MODAL_CLOSE: null,
+    GLOBAL_MODAL_ERROR: null,
+    GLOBAL_MODAL_WARNING: null,
+    GLOBAL_MODAL_SUCCESS: null
 });
 
-
 export const typeEnum = {
-       DEFAULT: 'default',
-       ERROR: 'error',
-       WARNING: 'warning',
-       SUCCESS: 'success'
+    DEFAULT: 'default',
+    ERROR: 'error',
+    WARNING: 'warning',
+    SUCCESS: 'success'
 };
 
-export const modalSizes  = {
-       LARGE: 'large',
-       SMALL: 'small'  
+export const modalSizes = {
+    LARGE: 'large',
+    SMALL: 'small'
 };
index 28674ea..b2273fa 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes, typeEnum} from './GlobalModalConstants.js';
+import { actionTypes, typeEnum } from './GlobalModalConstants.js';
 
 export default (state = null, action) => {
-       switch (action.type) {
-               case actionTypes.GLOBAL_MODAL_SHOW:                     
-                       return {
-                               ...action.data
-                       };
-               case actionTypes.GLOBAL_MODAL_ERROR:
-                       return {
-                               type: typeEnum.ERROR,
-                               modalClassName: 'notification-modal',
-                               ...action.data
-                       };
-               case actionTypes.GLOBAL_MODAL_WARNING:
-                       return {
-                               type: typeEnum.WARNING,
-                               modalClassName: 'notification-modal',
-                               ...action.data
-                       };
+    switch (action.type) {
+        case actionTypes.GLOBAL_MODAL_SHOW:
+            return {
+                ...action.data
+            };
+        case actionTypes.GLOBAL_MODAL_ERROR:
+            return {
+                type: typeEnum.ERROR,
+                modalClassName: 'notification-modal',
+                ...action.data
+            };
+        case actionTypes.GLOBAL_MODAL_WARNING:
+            return {
+                type: typeEnum.WARNING,
+                modalClassName: 'notification-modal',
+                ...action.data
+            };
 
-               case actionTypes.GLOBAL_MODAL_SUCCESS:
-                       return {
-                               type: typeEnum.SUCCESS,
-                               modalClassName: 'notification-modal',
-                               ...action.data
-                       };      
+        case actionTypes.GLOBAL_MODAL_SUCCESS:
+            return {
+                type: typeEnum.SUCCESS,
+                modalClassName: 'notification-modal',
+                ...action.data
+            };
 
-               case actionTypes.GLOBAL_MODAL_CLOSE:
-                       return null;                    
-               default:
-                       return state;
-       }
+        case actionTypes.GLOBAL_MODAL_CLOSE:
+            return null;
+        default:
+            return state;
+    }
 };
index b0f704d..cfd7575 100644 (file)
@@ -20,65 +20,63 @@ import BootstrapModal from 'react-bootstrap/lib/Modal.js';
 let nextModalId = 0;
 
 export default class Modal extends React.Component {
+    static Header = BootstrapModal.Header;
 
-       static Header = BootstrapModal.Header;
+    static Title = BootstrapModal.Title;
 
-       static Title = BootstrapModal.Title;
+    static Footer = BootstrapModal.Footer;
 
-       static Footer = BootstrapModal.Footer;
+    static Body = class ModalBody extends React.Component {
+        render() {
+            let { children, ...props } = this.props;
+            return (
+                <BootstrapModal.Body {...props}>{children}</BootstrapModal.Body>
+            );
+        }
 
-       static Body = class ModalBody extends React.Component {
+        componentDidMount() {
+            let element = ReactDOM.findDOMNode(this);
+            element.addEventListener('click', event => {
+                if (event.target.tagName === 'A') {
+                    event.preventDefault();
+                }
+            });
+            ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
+                element.addEventListener(eventType, event =>
+                    event.stopPropagation()
+                )
+            );
+        }
+    };
 
-               render() {
-                       let {children, ...props} = this.props;
-                       return (
-                               <BootstrapModal.Body {...props}>
-                                       {children}
-                               </BootstrapModal.Body>
-                       );
-               }
+    componentWillMount() {
+        this.modalId = `dox-ui-modal-${nextModalId++}`;
+    }
 
-               componentDidMount() {
-                       let element = ReactDOM.findDOMNode(this);
-                       element.addEventListener('click', event => {
-                               if (event.target.tagName === 'A') {
-                                       event.preventDefault();
-                               }
-                       });
-                       ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
-                               element.addEventListener(eventType, event => event.stopPropagation())
-                       );
-               }
-       };
+    componentDidMount() {
+        this.ensureRootClass();
+    }
 
-       componentWillMount() {
-               this.modalId = `dox-ui-modal-${nextModalId++}`;
-       }
+    componentDidUpdate() {
+        this.ensureRootClass();
+    }
 
-       componentDidMount() {
-               this.ensureRootClass();
-       }
+    ensureRootClass() {
+        let element = document.getElementById(this.modalId);
+        while (element && !element.hasAttribute('data-reactroot')) {
+            element = element.parentElement;
+        }
+        if (element && !element.classList.contains('dox-ui')) {
+            element.classList.add('dox-ui');
+        }
+    }
 
-       componentDidUpdate() {
-               this.ensureRootClass();
-       }
-
-       ensureRootClass() {
-               let element = document.getElementById(this.modalId);
-               while(element && !element.hasAttribute('data-reactroot')) {
-                       element = element.parentElement;
-               }
-               if (element && !element.classList.contains('dox-ui')) {
-                       element.classList.add('dox-ui');
-               }
-       }
-
-       render() {
-               let {children, ...props} = this.props;
-               return (
-                       <BootstrapModal {...props} id={this.modalId}>
-                               {children}
-                       </BootstrapModal>
-               );
-       }
+    render() {
+        let { children, ...props } = this.props;
+        return (
+            <BootstrapModal {...props} id={this.modalId}>
+                {children}
+            </BootstrapModal>
+        );
+    }
 }
index 054c1e2..7ed898e 100644 (file)
@@ -18,23 +18,21 @@ import React from 'react';
 import enhanceWithClickOutside from 'react-click-outside';
 
 class Overlay extends React.Component {
+    handleClickOutside() {
+        if (this.props.onClose) {
+            this.props.onClose();
+        }
+    }
 
-       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>
-               );
-       }
-
-};
+    render() {
+        return (
+            <div className="onboarding-overlay">
+                <div className="arrow-up" />
+                <div className="arrow-border" />
+                {this.props.children}
+            </div>
+        );
+    }
+}
 
 export default enhanceWithClickOutside(Overlay);
index 2eda7e6..61121df 100644 (file)
@@ -19,116 +19,159 @@ import classnames from 'classnames';
 import Collapse from 'react-bootstrap/lib/Collapse.js';
 
 class NavigationSideBar extends React.Component {
-       static PropTypes = {
-               activeItemId: PropTypes.string.isRequired,
-               onSelect: PropTypes.func,
-               onToggle: PropTypes.func,
-               groups: PropTypes.array,
-               disabled: PropTypes.bool
-       };
+    static PropTypes = {
+        activeItemId: PropTypes.string.isRequired,
+        onSelect: PropTypes.func,
+        onToggle: PropTypes.func,
+        groups: PropTypes.array,
+        disabled: PropTypes.bool
+    };
 
-       constructor(props) {
-               super(props);
-               this.state = {
-                       activeItemId: null
-               };
-               this.handleItemClicked = this.handleItemClicked.bind(this);
-       }
+    constructor(props) {
+        super(props);
+        this.state = {
+            activeItemId: null
+        };
+        this.handleItemClicked = this.handleItemClicked.bind(this);
+    }
 
-       render() {
-               let {groups, activeItemId, disabled = false} = this.props;
+    render() {
+        let { groups, activeItemId, disabled = false } = this.props;
 
-               return (
-                       <div className={`navigation-side-content ${disabled ? 'disabled' : ''}`}>
-                               {groups.map(group => (
-                                       <NavigationMenu menu={group} activeItemId={activeItemId} onNavigationItemClick={this.handleItemClicked} key={'menu_' + group.id} />
-                               ))}
-                       </div>
-               );
-       }
+        return (
+            <div
+                className={`navigation-side-content ${
+                    disabled ? 'disabled' : ''
+                }`}>
+                {groups.map(group => (
+                    <NavigationMenu
+                        menu={group}
+                        activeItemId={activeItemId}
+                        onNavigationItemClick={this.handleItemClicked}
+                        key={'menu_' + group.id}
+                    />
+                ))}
+            </div>
+        );
+    }
 
-       handleItemClicked(event, item) {
-               event.stopPropagation();
-               if(this.props.onToggle) {
-                       this.props.onToggle(this.props.groups, item.id);
-               }
-               if(item.onSelect) {
-                       item.onSelect();
-               }
-               if(this.props.onSelect) {
-                       this.props.onSelect(item);
-               }
-       }
+    handleItemClicked(event, item) {
+        event.stopPropagation();
+        if (this.props.onToggle) {
+            this.props.onToggle(this.props.groups, item.id);
+        }
+        if (item.onSelect) {
+            item.onSelect();
+        }
+        if (this.props.onSelect) {
+            this.props.onSelect(item);
+        }
+    }
 }
 
 class NavigationMenu extends React.Component {
-       static PropTypes = {
-               activeItemId: PropTypes.string.isRequired,
-               onNavigationItemClick: PropTypes.func,
-               menu: PropTypes.array
-       };
+    static PropTypes = {
+        activeItemId: PropTypes.string.isRequired,
+        onNavigationItemClick: PropTypes.func,
+        menu: PropTypes.array
+    };
 
-       render() {
-               const {menu, activeItemId, onNavigationItemClick} = this.props;
-               return (
-                       <div className='navigation-group'  key={menu.id}>
-                               <NavigationMenuHeader title={menu.name} />
-                               <NavigationMenuItems items={menu.items} activeItemId={activeItemId} onNavigationItemClick={onNavigationItemClick} />
-                       </div>);
-       }
+    render() {
+        const { menu, activeItemId, onNavigationItemClick } = this.props;
+        return (
+            <div className="navigation-group" key={menu.id}>
+                <NavigationMenuHeader title={menu.name} />
+                <NavigationMenuItems
+                    items={menu.items}
+                    activeItemId={activeItemId}
+                    onNavigationItemClick={onNavigationItemClick}
+                />
+            </div>
+        );
+    }
 }
 
 function NavigationMenuHeader(props) {
-       return <div className='group-name' data-test-id='navbar-group-name'>{props.title}</div>;
+    return (
+        <div className="group-name" data-test-id="navbar-group-name">
+            {props.title}
+        </div>
+    );
 }
 
 function getItemDataTestId(itemId) {
-       return itemId.split('|')[0];
+    return itemId.split('|')[0];
 }
 function NavigationMenuItems(props) {
-       const {items, activeItemId, onNavigationItemClick} = props;
-       return (
-               <div className='navigation-group-items'>
-                       {
-                               items && items.map(item => (<NavigationMenuItem key={'menuItem_' + item.id} item={item} activeItemId={activeItemId} onNavigationItemClick={onNavigationItemClick} />))
-                       }
-               </div>
-       );
+    const { items, activeItemId, onNavigationItemClick } = props;
+    return (
+        <div className="navigation-group-items">
+            {items &&
+                items.map(item => (
+                    <NavigationMenuItem
+                        key={'menuItem_' + item.id}
+                        item={item}
+                        activeItemId={activeItemId}
+                        onNavigationItemClick={onNavigationItemClick}
+                    />
+                ))}
+        </div>
+    );
 }
 
 function NavigationMenuItem(props) {
-       const {onNavigationItemClick, item, activeItemId} = props;
-       const isGroup = item.items && item.items.length > 0;
-       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-' + getItemDataTestId(item.id)}>
-                               <div>
-                                               {item.items.map(subItem => (<NavigationMenuItem key={'menuItem_' + subItem.id} item={subItem} onNavigationItemClick={onNavigationItemClick} activeItemId={activeItemId}  />)) }
-                               </div>
-                       </Collapse>
-                       }
-               </div>
-       );
+    const { onNavigationItemClick, item, activeItemId } = props;
+    const isGroup = item.items && item.items.length > 0;
+    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-' + getItemDataTestId(item.id)
+                    }>
+                    <div>
+                        {item.items.map(subItem => (
+                            <NavigationMenuItem
+                                key={'menuItem_' + subItem.id}
+                                item={subItem}
+                                onNavigationItemClick={onNavigationItemClick}
+                                activeItemId={activeItemId}
+                            />
+                        ))}
+                    </div>
+                </Collapse>
+            )}
+        </div>
+    );
 }
 
 function NavigationLink(props) {
-       const {item, activeItemId, onClick} = props;
-       // todo should this be button
-       return (
-               <div
-                       key={'navAction_' + item.id}
-                       className={classnames('navigation-group-item-name', {
-                               'selected': item.id === activeItemId,
-                               'disabled': item.disabled,
-                               'bold-name': item.expanded,
-                               'hidden': item.hidden
-                       })}
-                       onClick={(event) => onClick(event, item)}
-                       data-test-id={'navbar-group-item-' + getItemDataTestId(item.id)}>
-                       {item.name}
-               </div>
-       );
+    const { item, activeItemId, onClick } = props;
+    // todo should this be button
+    return (
+        <div
+            key={'navAction_' + item.id}
+            className={classnames('navigation-group-item-name', {
+                selected: item.id === activeItemId,
+                disabled: item.disabled,
+                'bold-name': item.expanded,
+                hidden: item.hidden
+            })}
+            onClick={event => onClick(event, item)}
+            data-test-id={'navbar-group-item-' + getItemDataTestId(item.id)}>
+            {item.name}
+        </div>
+    );
 }
 
 export default NavigationSideBar;
index 57fa86f..c9c5789 100644 (file)
@@ -17,125 +17,224 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-import {actionsEnum} from './VersionControllerConstants.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: 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 {version = {},  viewableVersions = [], onVersionSwitching, onMoreVersionsClick, callVCAction, onSave, isReadOnlyMode, itemPermission,
-                               isFormDataValid, onClose, onManagePermissions, permissions = {}, userInfo, usersList, itemName,
-                                onOpenCommentCommitModal, onOpenRevisionsModal, isManual, candidateInProcess, isArchived} = this.props;
-               return (
-                       <div className='version-controller-bar'>
-                               <div className={`vc-container ${candidateInProcess ? 'disabled' : ''}`}>
-                                       <div className='version-status-container'>
-                                               <VersionSelector
-                                                       viewableVersions={viewableVersions}
-                                                       version={version}
-                                                       onVersionSwitching={onVersionSwitching}
-                                                       onMoreVersionsClick={() => onMoreVersionsClick({itemName, users: usersList})}/>
-                                               {isArchived && <div className='depricated-item-status'>{i18n('Archived')}</div>}        
-                                       </div>                                  
-                                       <div className='save-submit-cancel-container'>
-                                               <ActionButtons onSubmit={callVCAction ? () => this.submit(callVCAction, version) : undefined}
-                                                       onRevert={callVCAction ? () => this.revert(callVCAction, version) : undefined}
-                                                       onOpenRevisionsModal={onOpenRevisionsModal}
-                                                       onSave={onSave ? () => onSave() : undefined}
-                                                       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}
-                                                       isArchived={isArchived}
-                                                       isReadOnlyMode={isReadOnlyMode || candidateInProcess}
-                                                       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>
-                       </div>
-               );
-       }
-
-       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);
-       }
-
-       revert(callVCAction, version) {
-               const action = actionsEnum.REVERT;
-               callVCAction(action, version);
-       }
-
-       sync(callVCAction, version) {
-               const action = actionsEnum.SYNC;
-               callVCAction(action, version);
-       }
-
-       commit(callVCAction, version, comment) {
-               const action = actionsEnum.COMMIT;
-               callVCAction(action, version, comment);
-       }
-
-       permissions() {
-
-       }
+    static propTypes = {
+        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 {
+            version = {},
+            viewableVersions = [],
+            onVersionSwitching,
+            onMoreVersionsClick,
+            callVCAction,
+            onSave,
+            isReadOnlyMode,
+            itemPermission,
+            isFormDataValid,
+            onClose,
+            onManagePermissions,
+            permissions = {},
+            userInfo,
+            usersList,
+            itemName,
+            onOpenCommentCommitModal,
+            onOpenRevisionsModal,
+            isManual,
+            candidateInProcess,
+            isArchived
+        } = this.props;
+        return (
+            <div className="version-controller-bar">
+                <div
+                    className={`vc-container ${
+                        candidateInProcess ? 'disabled' : ''
+                    }`}>
+                    <div className="version-status-container">
+                        <VersionSelector
+                            viewableVersions={viewableVersions}
+                            version={version}
+                            onVersionSwitching={onVersionSwitching}
+                            onMoreVersionsClick={() =>
+                                onMoreVersionsClick({
+                                    itemName,
+                                    users: usersList
+                                })
+                            }
+                        />
+                        {isArchived && (
+                            <div className="depricated-item-status">
+                                {i18n('Archived')}
+                            </div>
+                        )}
+                    </div>
+                    <div className="save-submit-cancel-container">
+                        <ActionButtons
+                            onSubmit={
+                                callVCAction
+                                    ? () => this.submit(callVCAction, version)
+                                    : undefined
+                            }
+                            onRevert={
+                                callVCAction
+                                    ? () => this.revert(callVCAction, version)
+                                    : undefined
+                            }
+                            onOpenRevisionsModal={onOpenRevisionsModal}
+                            onSave={onSave ? () => onSave() : undefined}
+                            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}
+                            isArchived={isArchived}
+                            isReadOnlyMode={
+                                isReadOnlyMode || candidateInProcess
+                            }
+                            isManual={isManual}
+                        />
+                        <div className="vc-separator" />
+                        <NotificationsView />
+                        {onClose && (
+                            <div
+                                className="vc-nav-item-close"
+                                onClick={() => onClose()}
+                                data-test-id="vc-cancel-btn">
+                                {' '}
+                                X
+                            </div>
+                        )}
+                    </div>
+                </div>
+            </div>
+        );
+    }
+
+    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);
+    }
+
+    revert(callVCAction, version) {
+        const action = actionsEnum.REVERT;
+        callVCAction(action, version);
+    }
+
+    sync(callVCAction, version) {
+        const action = actionsEnum.SYNC;
+        callVCAction(action, version);
+    }
+
+    commit(callVCAction, version, comment) {
+        const action = actionsEnum.COMMIT;
+        callVCAction(action, version, comment);
+    }
+
+    permissions() {}
 }
 
 function VersionSelector(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(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.name} ${viewVersion.status}`}</option>
-                                       );
-                               })
-                               }
-                               {!includedVersions.length &&
-                               <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>);
+    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(
+                        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.name
+                            } ${viewVersion.status}`}</option>
+                        );
+                    })}
+                {!includedVersions.length && (
+                    <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>
+    );
 }
 
 export default VersionController;
index ddb428a..54f10c1 100644 (file)
@@ -16,9 +16,9 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionsEnum = keyMirror({
-       REVERT: 'Revert',
-       SYNC: 'Sync',
-       SUBMIT: 'Submit',
-       COMMIT: 'Commit',
-       CREATE_PACKAGE: 'Create_Package'
+    REVERT: 'Revert',
+    SYNC: 'Sync',
+    SUBMIT: 'Submit',
+    COMMIT: 'Commit',
+    CREATE_PACKAGE: 'Create_Package'
 });
index b575081..4dfa117 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import enhanceWithClickOutside from 'react-click-outside';
 import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -22,88 +22,171 @@ 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>;
-       }
+    handleClickOutside() {
+        this.props.onClose();
+    }
+    render() {
+        return <div>{this.props.children}</div>;
+    }
 }
 
-const EnhancedClickOutsideWrapper = enhanceWithClickOutside(ClickOutsideWrapper);
+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 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 Separator = () => <div className="vc-separator" />;
 
-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 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, isArchived,
-       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 && !isArchived && <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 && 
-                               <div className='vc-submit-section'>
-                                       <Separator />
-                                       <SubmitButton onClick={onSubmit}
-                                               disabled={isReadOnlyMode || isOutOfSync || !isUpToDate || isCertified} />
-                               </div>
-                       }
-               </div>}
-       </div>
+const ActionButtons = ({
+    isReadOnlyMode,
+    onSubmit,
+    onRevert,
+    onSave,
+    isFormDataValid,
+    onClickPermissions,
+    onSync,
+    onCommit,
+    isArchived,
+    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 &&
+            !isArchived && (
+                <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 && (
+                        <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
+    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;
index 600eaee..ae0913f 100644 (file)
  */
 
 import React from 'react';
-import {connect} from 'react-redux';
+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 { 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
-
+    COMMIT: null,
+    COMMIT_SUBMIT: null
 });
 
-export const mapActionToProps = (dispatch) => {
-       return {
-               onClose: () => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               })
-       };
+export const mapActionToProps = dispatch => {
+    return {
+        onClose: () =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_CLOSE
+            })
+    };
 };
 
 class CommitCommentModal extends React.Component {
+    state = {
+        comment: ''
+    };
 
-       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')];
+    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>
-               );
-       }
+        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);
index 952bd4f..6e0ae81 100644 (file)
@@ -18,48 +18,76 @@ 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 Contributor = ({ name, role, id, userInfo }) => {
+    const selected = id === userInfo.userId ? 'selected' : '';
 
-       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>
-       );
+    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>
-       );
+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;
index ca5cb3d..cb10bb5 100644 (file)
@@ -17,22 +17,25 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 class ProgressBar extends React.Component {
-       static propTypes = {
-               label: PropTypes.string,
-               now: PropTypes.string.isRequired
-       }
-       render() {
-               let {label, now} = this.props;
+    static propTypes = {
+        label: PropTypes.string,
+        now: PropTypes.string.isRequired
+    };
+    render() {
+        let { label, now } = this.props;
 
-               return(
-                       <div className='progress-bar-view'>
-                               <div className='progress-bar-outside'>
-                                       <div style={{width: now + '%'}} className='progress-bar-inside'></div>
-                               </div>
-                               <div className='progress-bar-view-label'>{label}</div>
-                       </div>
-               );
-       }
+        return (
+            <div className="progress-bar-view">
+                <div className="progress-bar-outside">
+                    <div
+                        style={{ width: now + '%' }}
+                        className="progress-bar-inside"
+                    />
+                </div>
+                <div className="progress-bar-view-label">{label}</div>
+            </div>
+        );
+    }
 }
 
 export default ProgressBar;
index 3f8dbba..ee8a9dc 100644 (file)
@@ -5,26 +5,57 @@ import Button from 'sdc-ui/lib/react/Button.js';
 import uuid from 'uuid-js';
 
 export default class SelectActionTable extends React.Component {
-
-       render() {
-               let {columns, onAdd, isReadOnlyMode, children, onAddItem, numOfIcons} = this.props;
-               return (
-                       <div className={`select-action-table-view ${isReadOnlyMode ? 'disabled' : ''}`}>
-                               <div className='select-action-table-controllers'>
-                                       {onAdd && onAddItem &&
-                                       <Button btnType='link' disabled={isReadOnlyMode === true} color='primary' iconName='plus' data-test-id='select-action-table-add' onClick={onAdd}>{onAddItem}</Button>}
-                                       <SVGIcon name='trashO' className='dummy-icon' />
-                               </div>
-                               <div className='select-action-table'>
-                                       <div className='select-action-table-headers'>
-                                               {columns.map(column => <div key={uuid.create()} className='select-action-table-header'>{i18n(column)}</div>)}
-                                               {Array(numOfIcons).fill().map((e, i) => <SVGIcon name='trash-o' key={i} className='dummy-icon' />)}
-                                       </div>
-                                       <div className='select-action-table-body'>
-                                               {children}
-                                       </div>
-                               </div>
-                       </div>
-               );
-       }
+    render() {
+        let {
+            columns,
+            onAdd,
+            isReadOnlyMode,
+            children,
+            onAddItem,
+            numOfIcons
+        } = this.props;
+        return (
+            <div
+                className={`select-action-table-view ${
+                    isReadOnlyMode ? 'disabled' : ''
+                }`}>
+                <div className="select-action-table-controllers">
+                    {onAdd &&
+                        onAddItem && (
+                            <Button
+                                btnType="link"
+                                disabled={isReadOnlyMode === true}
+                                color="primary"
+                                iconName="plus"
+                                data-test-id="select-action-table-add"
+                                onClick={onAdd}>
+                                {onAddItem}
+                            </Button>
+                        )}
+                    <SVGIcon name="trashO" className="dummy-icon" />
+                </div>
+                <div className="select-action-table">
+                    <div className="select-action-table-headers">
+                        {columns.map(column => (
+                            <div
+                                key={uuid.create()}
+                                className="select-action-table-header">
+                                {i18n(column)}
+                            </div>
+                        ))}
+                        {Array(numOfIcons)
+                            .fill()
+                            .map((e, i) => (
+                                <SVGIcon
+                                    name="trash-o"
+                                    key={i}
+                                    className="dummy-icon"
+                                />
+                            ))}
+                    </div>
+                    <div className="select-action-table-body">{children}</div>
+                </div>
+            </div>
+        );
+    }
 }
index 2664c8e..20e4f24 100644 (file)
@@ -1,20 +1,28 @@
 import React from 'react';
 import SelectInput from 'nfvo-components/input/SelectInput.jsx';
 
-const SelectActionTableCell = ({options, selected, disabled, onChange, clearable = true, placeholder}) => {
-       return (
-               <div className='select-action-table-cell'>
-                       <SelectInput
-                               placeholder={placeholder}
-                               type='select'
-                               value={selected}
-                               data-test-id='select-action-table-dropdown'
-                               disabled={disabled}
-                               onChange={option => onChange(option ? option.value : null)}
-                               clearable={clearable}
-                               options={options} />
-               </div>
-       );
+const SelectActionTableCell = ({
+    options,
+    selected,
+    disabled,
+    onChange,
+    clearable = true,
+    placeholder
+}) => {
+    return (
+        <div className="select-action-table-cell">
+            <SelectInput
+                placeholder={placeholder}
+                type="select"
+                value={selected}
+                data-test-id="select-action-table-dropdown"
+                disabled={disabled}
+                onChange={option => onChange(option ? option.value : null)}
+                clearable={clearable}
+                options={options}
+            />
+        </div>
+    );
 };
 
 export default SelectActionTableCell;
index 260d39d..1c2c152 100644 (file)
@@ -3,38 +3,65 @@ 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';
 
-function tooltip (msg)  {
-       return (
-               <Tooltip className='select-action-table-error-tooltip' id='error-tooltip'>{msg}</Tooltip>
-       );
-};
+function tooltip(msg) {
+    return (
+        <Tooltip
+            className="select-action-table-error-tooltip"
+            id="error-tooltip">
+            {msg}
+        </Tooltip>
+    );
+}
 
-const IconWithOverlay = ({overlayMsg}) => (
-       <OverlayTrigger placement='bottom' overlay={tooltip(overlayMsg)}>
-               <SVGIcon name='errorCircle' color='negative'/>
-       </OverlayTrigger>
+const IconWithOverlay = ({ overlayMsg }) => (
+    <OverlayTrigger placement="bottom" overlay={tooltip(overlayMsg)}>
+        <SVGIcon name="errorCircle" color="negative" />
+    </OverlayTrigger>
 );
 
-function renderErrorOrCheck({hasError, overlayMsg}) {
-       if (hasError === undefined) {
-               return <SVGIcon name='angleRight' className='dummy-icon' />;
-       }
+function renderErrorOrCheck({ hasError, overlayMsg }) {
+    if (hasError === undefined) {
+        return <SVGIcon name="angleRight" className="dummy-icon" />;
+    }
 
-       if (hasError) {
-               return overlayMsg ? <IconWithOverlay overlayMsg={overlayMsg}/> :  <SVGIcon color='negative' name='errorCircle'/>;
-       }
+    if (hasError) {
+        return overlayMsg ? (
+            <IconWithOverlay overlayMsg={overlayMsg} />
+        ) : (
+            <SVGIcon color="negative" name="errorCircle" />
+        );
+    }
 
-       return <SVGIcon name='checkCircle' color='positive'/>;
+    return <SVGIcon name="checkCircle" color="positive" />;
 }
 
-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>
-               {onAction && <SVGIcon color='secondary' name={actionIcon} data-test-id={`select-action-table-${actionIcon}`} onClick={onAction} iconClassName={(showAction) ? '' : 'hideDelete'}/>}
-               {hasErrorIndication && renderErrorOrCheck({hasError, overlayMsg})}
-       </div>
+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>
+        {onAction && (
+            <SVGIcon
+                color="secondary"
+                name={actionIcon}
+                data-test-id={`select-action-table-${actionIcon}`}
+                onClick={onAction}
+                iconClassName={showAction ? '' : 'hideDelete'}
+            />
+        )}
+        {hasErrorIndication && renderErrorOrCheck({ hasError, overlayMsg })}
+    </div>
 );
 
 export default SelectActionTableRow;
index 682f3b6..39434fc 100644 (file)
@@ -1,16 +1,28 @@
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import {select} from 'd3-selection';
-import {tree, stratify} from 'd3-hierarchy';
-
+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 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;
@@ -18,164 +30,226 @@ const verticalSpaceBetweenNodes = 70;
 const NARROW_HORIZONTAL_SPACES = 47;
 const WIDE_HORIZONTAL_SPACES = 65;
 
-const stratifyFn = stratify().id(d => d.id).parentId(d => d.parent);
+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);
-               }
-       }
-
+    // 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} />
+            </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;
index b29920b..aca1a13 100644 (file)
 import React from 'react';
-import {storiesOf} from '@kadira/storybook';
-import {withKnobs} from '@kadira/storybook-addon-knobs';
+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'
-               }
-       ]
+    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);
+const divStyle = {
+    width: '200px',
+    borderStyle: 'solid',
+    borderColor: 'black',
+    border: '1px solid black'
 };
-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>
-));
+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>
+    ));
index 197625a..bdaf08b 100644 (file)
  */
 
 export default class Graph {
-       constructor() {
-               this.nodes = {};
-       }
+    constructor() {
+        this.nodes = {};
+    }
 
-       addNode(node) {
-               this.nodes[node] = [];
-       }
+    addNode(node) {
+        this.nodes[node] = [];
+    }
 
-       hasNode(node) {
-               return this.nodes.hasOwnProperty(node);
-       }
+    hasNode(node) {
+        return this.nodes.hasOwnProperty(node);
+    }
 
-       addEdge(firstNode, secondNode, payload) {
-               if (!this.hasNode(firstNode)) {
-                       this.addNode(firstNode);
-               }
+    addEdge(firstNode, secondNode, payload) {
+        if (!this.hasNode(firstNode)) {
+            this.addNode(firstNode);
+        }
 
-               if (!this.hasNode(secondNode)) {
-                       this.addNode(secondNode);
-               }
+        if (!this.hasNode(secondNode)) {
+            this.addNode(secondNode);
+        }
 
-               this.nodes[firstNode].push({...payload, target: secondNode});
-       }
+        this.nodes[firstNode].push({ ...payload, target: secondNode });
+    }
 
-       getEdges(node) {
-               return this.nodes[node];
-       }
-}
\ No newline at end of file
+    getEdges(node) {
+        return this.nodes[node];
+    }
+}
index 13dfb1f..5c55855 100644 (file)
  */
 import store from 'sdc-app/AppStore.js';
 import React from 'react';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SubmitErrorResponse from 'nfvo-components/SubmitErrorResponse.jsx';
 
 function showVariablesInMessage(variables, msg) {
-       let regex;
-       variables.forEach((value, index) => {
-               value = value.replace(';', ',');
-               regex = new RegExp('\'\%' + (index + 1) + '\'');
-               msg = msg.replace(regex, value);
-       });
-       return msg;
+    let regex;
+    variables.forEach((value, index) => {
+        value = value.replace(';', ',');
+        regex = new RegExp("'%" + (index + 1) + "'");
+        msg = msg.replace(regex, value);
+    });
+    return msg;
 }
 
 function parseCatalogExceptionObject(responseJSON) {
-       let title, msg;
-       if (responseJSON.requestError && responseJSON.requestError.policyException) {
-               title = 'Error: ' + responseJSON.requestError.policyException.messageId;
-               msg = responseJSON.requestError.policyException.text;
-       }
-       else if (responseJSON.requestError && responseJSON.requestError.serviceException) {
-               title = 'Error: ' + responseJSON.requestError.serviceException.messageId;
-               msg = responseJSON.requestError.serviceException.text;
-               let {variables} = responseJSON.requestError.serviceException;
-               if (variables) {
-                       msg = showVariablesInMessage(variables, msg);
-               }
-       }
-       else if (responseJSON.uploadDataErrors) {
-               title = i18n('Error: Upload Data Error');
-               msg = (<SubmitErrorResponse validationResponse={{uploadDataErrors: responseJSON.uploadDataErrors}} />);
-       }
-       else {
-               title = responseJSON.status;
-               msg = responseJSON.message;
-       }
-       return {title, msg};
+    let title, msg;
+    if (
+        responseJSON.requestError &&
+        responseJSON.requestError.policyException
+    ) {
+        title = 'Error: ' + responseJSON.requestError.policyException.messageId;
+        msg = responseJSON.requestError.policyException.text;
+    } else if (
+        responseJSON.requestError &&
+        responseJSON.requestError.serviceException
+    ) {
+        title =
+            'Error: ' + responseJSON.requestError.serviceException.messageId;
+        msg = responseJSON.requestError.serviceException.text;
+        let { variables } = responseJSON.requestError.serviceException;
+        if (variables) {
+            msg = showVariablesInMessage(variables, msg);
+        }
+    } else if (responseJSON.uploadDataErrors) {
+        title = i18n('Error: Upload Data Error');
+        msg = (
+            <SubmitErrorResponse
+                validationResponse={{
+                    uploadDataErrors: responseJSON.uploadDataErrors
+                }}
+            />
+        );
+    } else {
+        title = responseJSON.status;
+        msg = responseJSON.message;
+    }
+    return { title, msg };
 }
 
-var errorResponseHandler = (error) => {
-       let errorData;
-       if (error.data) {
-               errorData = parseCatalogExceptionObject(error.data);
-       }
-       else {
-               errorData = {
-                       title: error.statusText,
-                       msg: error.responseText ? error.responseText : i18n('GENERIC_ERROR'),
-               };
-       }
-       store.dispatch({
-               type: modalActionTypes.GLOBAL_MODAL_ERROR,
-               data: {
-                       ...errorData
-               }
-       });
+var errorResponseHandler = error => {
+    let errorData;
+    if (error.data) {
+        errorData = parseCatalogExceptionObject(error.data);
+    } else {
+        errorData = {
+            title: error.statusText,
+            msg: error.responseText ? error.responseText : i18n('GENERIC_ERROR')
+        };
+    }
+    store.dispatch({
+        type: modalActionTypes.GLOBAL_MODAL_ERROR,
+        data: {
+            ...errorData
+        }
+    });
 };
 
 export default errorResponseHandler;
index 220fe07..dc351af 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-var keyMirror = function (obj) {
-       var ret = {};
-       var key;
-       var val;
-       if (!(obj instanceof Object && !Array.isArray(obj))) {
-               throw new Error('keyMirror(...): Argument must be an object.');
-       }
-       for (key in obj) {
-               if (obj.hasOwnProperty(key)) {
-                       val = obj[key];
-                       if (val instanceof Object) {
-                               ret[key] = keyMirror(obj[key]);
-                       } else if(val !== null && val !== undefined){
-                               ret[key] = val;
-                       }
-                       else {
-                               ret[key] = Symbol(key);
-                       }
-               }
-       }
-       return Object.freeze(ret);
+var keyMirror = function(obj) {
+    var ret = {};
+    var key;
+    var val;
+    if (!(obj instanceof Object && !Array.isArray(obj))) {
+        throw new Error('keyMirror(...): Argument must be an object.');
+    }
+    for (key in obj) {
+        if (obj.hasOwnProperty(key)) {
+            val = obj[key];
+            if (val instanceof Object) {
+                ret[key] = keyMirror(obj[key]);
+            } else if (val !== null && val !== undefined) {
+                ret[key] = val;
+            } else {
+                ret[key] = Symbol(key);
+            }
+        }
+    }
+    return Object.freeze(ret);
 };
 
-export default keyMirror;
\ No newline at end of file
+export default keyMirror;
index 5b07986..1a5817d 100644 (file)
@@ -18,7 +18,7 @@ import md5 from 'md5';
 import axios from 'axios';
 
 import store from 'sdc-app/AppStore.js';
-import {actionTypes as LoaderConstants} from 'nfvo-components/loader/LoaderConstants.js';
+import { actionTypes as LoaderConstants } from 'nfvo-components/loader/LoaderConstants.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import errorResponseHandler from './ErrorResponseHandler.js';
 
@@ -39,124 +39,133 @@ const STORAGE_AUTH_KEY = 'sdc-auth-token';
 const REQUEST_ID_HEADER = 'X-ECOMP-RequestID';
 const CONTENT_MD5_HEADER = 'Content-MD5';
 
-
 function applySecurity(options, data) {
-       let headers = options.headers || (options.headers = {});
-
-       let authToken = localStorage.getItem(STORAGE_AUTH_KEY);
-       if (authToken) {
-               headers[AUTHORIZATION_HEADER] = authToken;
-       }
-
-       let catalogApiHeaders = Configuration.get('CatalogApiHeaders'),
-               catalogUidHeader = catalogApiHeaders && catalogApiHeaders.userId;
-       if (catalogUidHeader) {
-               headers[catalogUidHeader.name] = catalogUidHeader.value;
-       }
-
-       headers[REQUEST_ID_HEADER] = uuid.create().toString();
-       if (options.md5) {
-               let headers = options.headers;
-               headers[CONTENT_MD5_HEADER] = window.btoa(md5(JSON.stringify(data)).toLowerCase());
-       }
+    let headers = options.headers || (options.headers = {});
+
+    let authToken = localStorage.getItem(STORAGE_AUTH_KEY);
+    if (authToken) {
+        headers[AUTHORIZATION_HEADER] = authToken;
+    }
+
+    let catalogApiHeaders = Configuration.get('CatalogApiHeaders'),
+        catalogUidHeader = catalogApiHeaders && catalogApiHeaders.userId;
+    if (catalogUidHeader) {
+        headers[catalogUidHeader.name] = catalogUidHeader.value;
+    }
+
+    headers[REQUEST_ID_HEADER] = uuid.create().toString();
+    if (options.md5) {
+        let headers = options.headers;
+        headers[CONTENT_MD5_HEADER] = window.btoa(
+            md5(JSON.stringify(data)).toLowerCase()
+        );
+    }
 }
 
-
 function handleSuccess(responseHeaders, requestHeaders) {
-       let authToken = responseHeaders[AUTHORIZATION_HEADER];
-       let prevToken = requestHeaders && requestHeaders[AUTHORIZATION_HEADER];
-       if (authToken && authToken !== prevToken) {
-               if (authToken === 'null') {
-                       localStorage.removeItem(STORAGE_AUTH_KEY);
-               } else {
-                       localStorage.setItem(STORAGE_AUTH_KEY, authToken);
-               }
-       }
+    let authToken = responseHeaders[AUTHORIZATION_HEADER];
+    let prevToken = requestHeaders && requestHeaders[AUTHORIZATION_HEADER];
+    if (authToken && authToken !== prevToken) {
+        if (authToken === 'null') {
+            localStorage.removeItem(STORAGE_AUTH_KEY);
+        } else {
+            localStorage.setItem(STORAGE_AUTH_KEY, authToken);
+        }
+    }
 }
 
-class RestAPIUtil  {
-       handleRequest(url, type, options = {}, data){
-               if (DEBUG) {
-                       console.log('axios --> Making REST call (' + type + '): ' + url);
-               }
-
-               applySecurity(options, data);
-
-               // TODO see ig necessary or in transformrequest funtion
-               if (type === POST || type === PUT) {
-                       if (data instanceof FormData) {
-                               options.headers.contentType = MULTIPART_FORM_DATA;
-                       }
-                       else {
-                               options.headers.contentType = APPLICATION_JSON;
-//                             config.data = JSON.stringify(data);
-                       }
-
-               } else {
-                       data = null;
-               }
-
-               let config = {
-                       method: type,
-                       url: url,
-                       headers : options.headers,
-                       data : data
-               };
-
-               store.dispatch({type: LoaderConstants.SEND_REQUEST, url: url});
-               if (options.dataType === BINARY) {
-                       config.responseType = 'arraybuffer';
-                       return axios(config).
-                       then(result => {
-                               store.dispatch({type: LoaderConstants.RECEIVE_RESPONSE, url : result.config.url});
-                               return ({
-                                       blob : new Blob([result.data] ),
-                                       headers : result.headers
-                               });
-                       }).catch(error => {
-                               store.dispatch({type: LoaderConstants.RECEIVE_RESPONSE, url : error.config.url});
-                               errorResponseHandler(error.response); });
-               } else {
-                       return axios(config).
-                       then(result => {
-                               store.dispatch({type: LoaderConstants.RECEIVE_RESPONSE, url : result.config.url});
-                               handleSuccess(result.headers, result.config.headers);
-                               return result.data;
-                       }).catch(error => {
-                               store.dispatch({type: LoaderConstants.RECEIVE_RESPONSE, url : error.config.url});
-                               errorResponseHandler(error.response);
-                               return Promise.reject({responseJSON: error.response.data});
-                       });
-               }
-
-       }
-
-       fetch(url, options) {
-               return this.handleRequest(url, GET, options);
-       }
-
-       get(url, options) {
-               return this.fetch(url, options);
-       }
-
-       post(url, data, options) {
-               return this.handleRequest(url, POST, options, data);
-       }
-
-       put(url, data, options) {
-               return this.handleRequest(url, PUT, options, data);
-       }
-
-       destroy(url, options) {
-               return this.handleRequest(url, DELETE, options);
-       }
-
-
-
+class RestAPIUtil {
+    handleRequest(url, type, options = {}, data) {
+        if (DEBUG) {
+            console.log('axios --> Making REST call (' + type + '): ' + url);
+        }
+
+        applySecurity(options, data);
+
+        // TODO see ig necessary or in transformrequest funtion
+        if (type === POST || type === PUT) {
+            if (data instanceof FormData) {
+                options.headers.contentType = MULTIPART_FORM_DATA;
+            } else {
+                options.headers.contentType = APPLICATION_JSON;
+                //                             config.data = JSON.stringify(data);
+            }
+        } else {
+            data = null;
+        }
+
+        let config = {
+            method: type,
+            url: url,
+            headers: options.headers,
+            data: data
+        };
+
+        store.dispatch({ type: LoaderConstants.SEND_REQUEST, url: url });
+        if (options.dataType === BINARY) {
+            config.responseType = 'arraybuffer';
+            return axios(config)
+                .then(result => {
+                    store.dispatch({
+                        type: LoaderConstants.RECEIVE_RESPONSE,
+                        url: result.config.url
+                    });
+                    return {
+                        blob: new Blob([result.data]),
+                        headers: result.headers
+                    };
+                })
+                .catch(error => {
+                    store.dispatch({
+                        type: LoaderConstants.RECEIVE_RESPONSE,
+                        url: error.config.url
+                    });
+                    errorResponseHandler(error.response);
+                });
+        } else {
+            return axios(config)
+                .then(result => {
+                    store.dispatch({
+                        type: LoaderConstants.RECEIVE_RESPONSE,
+                        url: result.config.url
+                    });
+                    handleSuccess(result.headers, result.config.headers);
+                    return result.data;
+                })
+                .catch(error => {
+                    store.dispatch({
+                        type: LoaderConstants.RECEIVE_RESPONSE,
+                        url: error.config.url
+                    });
+                    errorResponseHandler(error.response);
+                    return Promise.reject({
+                        responseJSON: error.response.data
+                    });
+                });
+        }
+    }
+
+    fetch(url, options) {
+        return this.handleRequest(url, GET, options);
+    }
+
+    get(url, options) {
+        return this.fetch(url, options);
+    }
+
+    post(url, data, options) {
+        return this.handleRequest(url, POST, options, data);
+    }
+
+    put(url, data, options) {
+        return this.handleRequest(url, PUT, options, data);
+    }
+
+    destroy(url, options) {
+        return this.handleRequest(url, DELETE, options);
+    }
 }
 
 const instance = new RestAPIUtil();
 
-
-
 export default instance;
index bddd49c..990701c 100644 (file)
  */
 
 function getTimestampString() {
-       let date = new Date();
-       let z = n => n < 10 ? '0' + n : n;
-       return `${date.getFullYear()}-${z(date.getMonth())}-${z(date.getDate())}_${z(date.getHours())}-${z(date.getMinutes())}`;
+    let date = new Date();
+    let z = n => (n < 10 ? '0' + n : n);
+    return `${date.getFullYear()}-${z(date.getMonth())}-${z(
+        date.getDate()
+    )}_${z(date.getHours())}-${z(date.getMinutes())}`;
 }
 
+export default function showFileSaveDialog({
+    blob,
+    headers,
+    defaultFilename,
+    addTimestamp
+}) {
+    let filename;
+    let contentDisposition = headers['content-disposition']
+        ? headers['content-disposition']
+        : '';
+    let match = contentDisposition
+        ? contentDisposition.match(/filename=(.*?)(;|$)/)
+        : false;
+    if (match) {
+        filename = match[1];
+    } else {
+        filename = defaultFilename;
+    }
 
-export default function showFileSaveDialog({blob, headers, defaultFilename, addTimestamp}) {
-       let filename;
-       let contentDisposition = headers['content-disposition'] ? headers['content-disposition'] : '';
-       let match = contentDisposition ? contentDisposition.match(/filename=(.*?)(;|$)/) : false;
-       if (match) {
-               filename = match[1];
-       } else {
-               filename = defaultFilename;
-       }
+    if (addTimestamp) {
+        filename = filename.replace(
+            /(^.*?)\.([^.]+$)/,
+            `$1_${getTimestampString()}.$2`
+        );
+    }
 
-       if (addTimestamp) {
-               filename = filename.replace(/(^.*?)\.([^.]+$)/, `$1_${getTimestampString()}.$2`);
-       }
-
-       let link = document.createElement('a');
-       let url = URL.createObjectURL(blob);
-       link.href = url;
-       link.download = filename;
-       link.style.display = 'none';
-       document.body.appendChild(link);
-       link.click();
-       setTimeout(function(){
-               document.body.removeChild(link);
-               URL.revokeObjectURL(url);
-       }, 0);
-};
+    let link = document.createElement('a');
+    let url = URL.createObjectURL(blob);
+    link.href = url;
+    link.download = filename;
+    link.style.display = 'none';
+    document.body.appendChild(link);
+    link.click();
+    setTimeout(function() {
+        document.body.removeChild(link);
+        URL.revokeObjectURL(url);
+    }, 0);
+}
index e1d4c54..37de994 100644 (file)
  */
 import UUID from 'uuid-js';
 
-let toCustomUUID = (uuid) => {
-       return 'U' + uuid.replace(/-/g, '');
+let toCustomUUID = uuid => {
+    return 'U' + uuid.replace(/-/g, '');
 };
 
 let getUUID = function(num, isSync) {
-       if (isSync) {
-               let uuid;
-               if (!num) {
-                       uuid = toCustomUUID(UUID.create().toString());
-               } else {
-                       uuid = [];
-                       for (var i = 0; i < num; i++) {
-                               uuid[i] = toCustomUUID(UUID.create().toString());
-                       }
-               }
-               if (num === 1) {
-                       return uuid[0];
-               } else {
-                       return uuid;
-               }
-       }
-       return new Promise(resolve => {
-               let uuid;
-               if (!num) {
-                       uuid = toCustomUUID(UUID.create().toString());
-               } else {
-                       uuid = [];
-                       for (var i = 0; i < num; i++) {
-                               uuid[i] = toCustomUUID(UUID.create().toString());
-                       }
-               }
-               setTimeout(() => resolve(uuid), 100);
-       });
+    if (isSync) {
+        let uuid;
+        if (!num) {
+            uuid = toCustomUUID(UUID.create().toString());
+        } else {
+            uuid = [];
+            for (var i = 0; i < num; i++) {
+                uuid[i] = toCustomUUID(UUID.create().toString());
+            }
+        }
+        if (num === 1) {
+            return uuid[0];
+        } else {
+            return uuid;
+        }
+    }
+    return new Promise(resolve => {
+        let uuid;
+        if (!num) {
+            uuid = toCustomUUID(UUID.create().toString());
+        } else {
+            uuid = [];
+            for (var i = 0; i < num; i++) {
+                uuid[i] = toCustomUUID(UUID.create().toString());
+            }
+        }
+        setTimeout(() => resolve(uuid), 100);
+    });
 };
 
 export default getUUID;
index 0cb1943..324198e 100644 (file)
@@ -18,119 +18,189 @@ import * as ValidatorJS from 'validator';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 class Validator {
-       static get globalValidationFunctions() {
-               return {
-                       required: value => {
-                               return typeof value === 'string' ? value.replace(/\s+/g, '') !== '' : value !== '';
-                       },
-                       requiredChooseOption: value => value !== '',
-                       maxLength: (value, length) => ValidatorJS.isLength(value, {max: length}),
-                       minLength: (value, length) => ValidatorJS.isLength(value, {min: length}),
-                       pattern: (value, pattern) => ValidatorJS.matches(value, pattern),
-                       numeric: value => {
-                               if (value === '') {
-                                       // to allow empty value which is not zero
-                                       return true;
-                               }
-                               return ValidatorJS.isNumeric(value);
-                       },
-                       maximum: (value, maxValue) => {return (value === undefined) ? true : (value <= maxValue);},
-                       minimum: (value, minValue) => {return (value === undefined) ? true : (value >= minValue);},
-                       maximumExclusive: (value, maxValue) => {return (value === undefined) ? true : (value < maxValue);},
-                       minimumExclusive: (value, minValue) => {return (value === undefined) ? true : (value > minValue);},
-                       alphanumeric: value => ValidatorJS.isAlphanumeric(value),
-                       alphanumericWithSpaces: value => ValidatorJS.isAlphanumeric(value.replace(/ /g, '')),
-                       validateName: value => ValidatorJS.isAlphanumeric(value.replace(/\s|\.|\_|\-/g, ''), 'en-US'),
-                       validateVendorName: value => ValidatorJS.isAlphanumeric(value.replace(/[\x7F-\xFF]|\s/g, ''), 'en-US'),
-                       freeEnglishText: value => ValidatorJS.isAlphanumeric(value.replace(/\s|\.|\_|\-|\,|\(|\)|\?/g, ''), 'en-US'),
-                       email: value => ValidatorJS.isEmail(value),
-                       ip: value => ValidatorJS.isIP(value),
-                       url: value => ValidatorJS.isURL(value),
-                       alphanumericWithUnderscores: value => ValidatorJS.isAlphanumeric(value.replace(/_/g, '')),
-                       requiredChoiceWithOther: (value, otherValue) => {
-                               let chosen = value.choice;
-                               // if we have an empty multiple select we have a problem since it's required
-                               let validationFunc = this.globalValidationFunctions['required'];
-                               if (value.choices) {
-                                       if (value.choices.length === 0) {
-                                               return  false;
-                                       } else {
-                                               // continuing validation with the first chosen value in case we have the 'Other' field
-                                               chosen = value.choices[0];
-                                       }
-                               }
-                               if (chosen !== otherValue) {
-                                       return validationFunc(chosen, true);
-                               } else { // when 'Other' was chosen, validate other value
-                                       return validationFunc(value.other, true);
-                               }
-                       }
-               };
-       }
+    static get globalValidationFunctions() {
+        return {
+            required: value => {
+                return typeof value === 'string'
+                    ? value.replace(/\s+/g, '') !== ''
+                    : value !== '';
+            },
+            requiredChooseOption: value => value !== '',
+            maxLength: (value, length) =>
+                ValidatorJS.isLength(value, { max: length }),
+            minLength: (value, length) =>
+                ValidatorJS.isLength(value, { min: length }),
+            pattern: (value, pattern) => ValidatorJS.matches(value, pattern),
+            numeric: value => {
+                if (value === '') {
+                    // to allow empty value which is not zero
+                    return true;
+                }
+                return ValidatorJS.isNumeric(value);
+            },
+            maximum: (value, maxValue) => {
+                return value === undefined ? true : value <= maxValue;
+            },
+            minimum: (value, minValue) => {
+                return value === undefined ? true : value >= minValue;
+            },
+            maximumExclusive: (value, maxValue) => {
+                return value === undefined ? true : value < maxValue;
+            },
+            minimumExclusive: (value, minValue) => {
+                return value === undefined ? true : value > minValue;
+            },
+            alphanumeric: value => ValidatorJS.isAlphanumeric(value),
+            alphanumericWithSpaces: value =>
+                ValidatorJS.isAlphanumeric(value.replace(/ /g, '')),
+            validateName: value =>
+                ValidatorJS.isAlphanumeric(
+                    value.replace(/\s|\.|\_|\-/g, ''),
+                    'en-US'
+                ),
+            validateVendorName: value =>
+                ValidatorJS.isAlphanumeric(
+                    value.replace(/[\x7F-\xFF]|\s/g, ''),
+                    'en-US'
+                ),
+            freeEnglishText: value =>
+                ValidatorJS.isAlphanumeric(
+                    value.replace(/\s|\.|\_|\-|\,|\(|\)|\?/g, ''),
+                    'en-US'
+                ),
+            email: value => ValidatorJS.isEmail(value),
+            ip: value => ValidatorJS.isIP(value),
+            url: value => ValidatorJS.isURL(value),
+            alphanumericWithUnderscores: value =>
+                ValidatorJS.isAlphanumeric(value.replace(/_/g, '')),
+            requiredChoiceWithOther: (value, otherValue) => {
+                let chosen = value.choice;
+                // if we have an empty multiple select we have a problem since it's required
+                let validationFunc = this.globalValidationFunctions['required'];
+                if (value.choices) {
+                    if (value.choices.length === 0) {
+                        return false;
+                    } else {
+                        // continuing validation with the first chosen value in case we have the 'Other' field
+                        chosen = value.choices[0];
+                    }
+                }
+                if (chosen !== otherValue) {
+                    return validationFunc(chosen, true);
+                } else {
+                    // when 'Other' was chosen, validate other value
+                    return validationFunc(value.other, true);
+                }
+            }
+        };
+    }
 
-       static get globalValidationMessagingFunctions() {
-               return {
-                       required: () => i18n('Field is required'),
-                       requiredChooseOption: () => i18n('Field should have one of these options'),
-                       requiredChoiceWithOther: () => i18n('Field is required'),
-                       maxLength: (value, maxLength) => i18n('Field value has exceeded it\'s limit, {maxLength}. current length: {length}', {
-                               length: value.length,
-                               maxLength
-                       }),
-                       minLength: (value, minLength) => i18n('Field value should contain at least {minLength} characters.', {minLength: minLength}),
-                       pattern: (value, pattern) => i18n('Field value should match the pattern: {pattern}.', {pattern: pattern}),
-                       numeric: () => i18n('Field value should contain numbers only.'),
-                       maximum: (value, maxValue) => i18n('Field value should be less or equal to: {maxValue}.', {maxValue: maxValue}),
-                       minimum: (value, minValue) => i18n('Field value should be at least: {minValue}.', {minValue: minValue.toString()}),
-                       maximumExclusive: (value, maxValue) => i18n('Field value should be less than: {maxValue}.', {maxValue: maxValue}),
-                       minimumExclusive: (value, minValue) => i18n('Field value should be more than: {minValue}.', {minValue: minValue.toString()}),
-                       alphanumeric: () => i18n('Field value should contain letters or digits only.'),
-                       alphanumericWithSpaces: () => i18n('Field value should contain letters, digits or spaces only.'),
-                       validateName: ()=> i18n('Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
-                       validateVendorName: ()=> i18n('Field value should contain English letters digits and spaces only.'),
-                       freeEnglishText: ()=> i18n('Field value should contain  English letters, digits , spaces, underscores, dashes and dots only.'),
-                       email: () => i18n('Field value should be a valid email address.'),
-                       ip: () => i18n('Field value should be a valid ip address.'),
-                       url: () => i18n('Field value should be a valid url address.'),
-                       general: () => i18n('Field value is invalid.'),
-                       alphanumericWithUnderscores: () => i18n('Field value should contain letters, digits or _ only.')
-               };
-       }
+    static get globalValidationMessagingFunctions() {
+        return {
+            required: () => i18n('Field is required'),
+            requiredChooseOption: () =>
+                i18n('Field should have one of these options'),
+            requiredChoiceWithOther: () => i18n('Field is required'),
+            maxLength: (value, maxLength) =>
+                i18n(
+                    "Field value has exceeded it's limit, {maxLength}. current length: {length}",
+                    {
+                        length: value.length,
+                        maxLength
+                    }
+                ),
+            minLength: (value, minLength) =>
+                i18n(
+                    'Field value should contain at least {minLength} characters.',
+                    {
+                        minLength: minLength
+                    }
+                ),
+            pattern: (value, pattern) =>
+                i18n('Field value should match the pattern: {pattern}.', {
+                    pattern: pattern
+                }),
+            numeric: () => i18n('Field value should contain numbers only.'),
+            maximum: (value, maxValue) =>
+                i18n('Field value should be less or equal to: {maxValue}.', {
+                    maxValue: maxValue
+                }),
+            minimum: (value, minValue) =>
+                i18n('Field value should be at least: {minValue}.', {
+                    minValue: minValue.toString()
+                }),
+            maximumExclusive: (value, maxValue) =>
+                i18n('Field value should be less than: {maxValue}.', {
+                    maxValue: maxValue
+                }),
+            minimumExclusive: (value, minValue) =>
+                i18n('Field value should be more than: {minValue}.', {
+                    minValue: minValue.toString()
+                }),
+            alphanumeric: () =>
+                i18n('Field value should contain letters or digits only.'),
+            alphanumericWithSpaces: () =>
+                i18n(
+                    'Field value should contain letters, digits or spaces only.'
+                ),
+            validateName: () =>
+                i18n(
+                    'Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'
+                ),
+            validateVendorName: () =>
+                i18n(
+                    'Field value should contain English letters digits and spaces only.'
+                ),
+            freeEnglishText: () =>
+                i18n(
+                    'Field value should contain  English letters, digits , spaces, underscores, dashes and dots only.'
+                ),
+            email: () => i18n('Field value should be a valid email address.'),
+            ip: () => i18n('Field value should be a valid ip address.'),
+            url: () => i18n('Field value should be a valid url address.'),
+            general: () => i18n('Field value is invalid.'),
+            alphanumericWithUnderscores: () =>
+                i18n('Field value should contain letters, digits or _ only.')
+        };
+    }
 
-       static validateItem(value, data, type) {
-               let validationFunc = this.globalValidationFunctions[type];
-               const isValid = validationFunc(value, data);
-               let errorText = '';
-               if (!isValid) {
-                       errorText = this.globalValidationMessagingFunctions[type](value, data);
-               }
-               return {
-                       isValid,
-                       errorText
-               };
-       }
+    static validateItem(value, data, type) {
+        let validationFunc = this.globalValidationFunctions[type];
+        const isValid = validationFunc(value, data);
+        let errorText = '';
+        if (!isValid) {
+            errorText = this.globalValidationMessagingFunctions[type](
+                value,
+                data
+            );
+        }
+        return {
+            isValid,
+            errorText
+        };
+    }
 
-       static validate(fieldName, value, validations, state, customValidations) {
-               let result = { isValid: true, errorText: '' };
-               for (let validation of validations) {
-                       result = this.validateItem(value, validation.data, validation.type);
-                       if (!result.isValid) {
-                               return result;
-                       }
-               }
-               if (customValidations) {
-                       let validationFunc = customValidations[fieldName];
-                       if (validationFunc) {
-                               result = validationFunc(value, state);
-                       }
-               }
-               return result;
-       }
+    static validate(fieldName, value, validations, state, customValidations) {
+        let result = { isValid: true, errorText: '' };
+        for (let validation of validations) {
+            result = this.validateItem(value, validation.data, validation.type);
+            if (!result.isValid) {
+                return result;
+            }
+        }
+        if (customValidations) {
+            let validationFunc = customValidations[fieldName];
+            if (validationFunc) {
+                result = validationFunc(value, state);
+            }
+        }
+        return result;
+    }
 
-       static isItemNameAlreadyExistsInList({itemId, itemName, list}) {
-               itemName = itemName.toLowerCase();
-               return list[itemName] && list[itemName] !== itemId;
-       }
+    static isItemNameAlreadyExistsInList({ itemId, itemName, list }) {
+        itemName = itemName.toLowerCase();
+        return list[itemName] && list[itemName] !== itemId;
+    }
 }
 
 export default Validator;
index c9dd10f..69f44d4 100644 (file)
 
 import store from 'sdc-app/AppStore.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from 'sdc-app/onboarding/userNotifications/UserNotificationsConstants.js';
+import { actionTypes } from 'sdc-app/onboarding/userNotifications/UserNotificationsConstants.js';
 
-
-export const websocketUrl = 'ws://' + window.location.hostname + ':' + Configuration.get('websocketPort')
-       + '/'  + Configuration.get('websocketPath');
+export const websocketUrl =
+    'ws://' +
+    window.location.hostname +
+    ':' +
+    Configuration.get('websocketPort') +
+    '/' +
+    Configuration.get('websocketPath');
 
 /***
  * Websocket is treated like a singleton. only need one for the application.
  */
 var websocket;
 
-
 export default {
+    open(url, { lastScanned }) {
+        if (
+            websocket === undefined ||
+            websocket.readyState === websocket.CLOSED
+        ) {
+            websocket = new WebSocket(
+                `${url}?LAST_DELIVERED_EVENT_ID=${lastScanned}`
+            );
+            websocket.onmessage = event =>
+                store.dispatch({
+                    type: actionTypes.NOTIFICATION,
+                    data: JSON.parse(event.data)
+                });
+            websocket.onclose = event => {
+                if (event.code && event.code === 1001) {
+                    // - Idle Timeout
+                    const { lastScanned } = store.getState().notifications;
+                    console.log('Reconnecting to Websocket');
+                    this.open(websocketUrl, { lastScanned });
+                }
+            };
+            websocket.onerror = event => console.log(event);
+        }
+    },
 
-       open(url, {lastScanned}) {
-               if (websocket === undefined || websocket.readyState === websocket.CLOSED) {
-                       websocket = new WebSocket(`${url}?LAST_DELIVERED_EVENT_ID=${lastScanned}`);
-                       websocket.onmessage = event => store.dispatch({
-                               type: actionTypes.NOTIFICATION,
-                               data: JSON.parse(event.data)
-                       });
-                       websocket.onclose = event => {
-                               if(event.code && event.code === 1001) { // - Idle Timeout
-                                       const {lastScanned} = store.getState().notifications;
-                                       console.log('Reconnecting to Websocket');
-                                       this.open(websocketUrl, {lastScanned});
-                               }
-                       };
-                       websocket.onerror = event => console.log(event);
-               }
-       },
-
-       close() {
-               if (websocket !== undefined) {
-                       websocket.close();
-               }
-       }
+    close() {
+        if (websocket !== undefined) {
+            websocket.close();
+        }
+    }
 };
index 5ab0c76..0cac3cd 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
 function getValueFromObject(element) {
-       return element.choices && element.choices.length > 0 && element.choices[0] !== '' && element.choices[0] !== optionInputOther.OTHER ||
-                       element.other && element.choices[0] === optionInputOther.OTHER ?
-                       element : undefined;
+    return (element.choices &&
+        element.choices.length > 0 &&
+        element.choices[0] !== '' &&
+        element.choices[0] !== optionInputOther.OTHER) ||
+        (element.other && element.choices[0] === optionInputOther.OTHER)
+        ? element
+        : undefined;
 }
 
 function getValueFromVariable(variable) {
-       return variable ? variable : undefined;
+    return variable ? variable : undefined;
 }
 
 function getArrayData(variable) {
-       return variable.length ? variable : undefined;
+    return variable.length ? variable : undefined;
 }
 
- let getValue = element => {
-       return typeof element === 'object' ?
-               element instanceof Array ? getArrayData(element) : getValueFromObject(element) :
-               getValueFromVariable(element);
- };
+let getValue = element => {
+    return typeof element === 'object'
+        ? element instanceof Array
+          ? getArrayData(element)
+          : getValueFromObject(element)
+        : getValueFromVariable(element);
+};
 
 export function getStrValue(choiceObject) {
-       if (!choiceObject) {
-               return undefined;
-       }
-       if (choiceObject.choice && choiceObject.choice !== '' && choiceObject.choice !== optionInputOther.OTHER) {
-               return choiceObject.choice;
-       }
-       else if (choiceObject.other && choiceObject.choice === optionInputOther.OTHER) {
-               return choiceObject.other;
-       }
+    if (!choiceObject) {
+        return undefined;
+    }
+    if (
+        choiceObject.choice &&
+        choiceObject.choice !== '' &&
+        choiceObject.choice !== optionInputOther.OTHER
+    ) {
+        return choiceObject.choice;
+    } else if (
+        choiceObject.other &&
+        choiceObject.choice === optionInputOther.OTHER
+    ) {
+        return choiceObject.other;
+    }
 }
 
- export default getValue;
+export default getValue;
index ef97b8b..43a183d 100644 (file)
@@ -22,88 +22,94 @@ import i18nJson from 'i18nJson';
  Intl libs are using out dated transpailer from ecmascript6.
  *  TODO: As soon as they fix it, remove this assignments!!!
  * */
-var Intl               = window.Intl || IntlObj.default,
-       IntlMessageFormat  = IntlMessageFormatObj.default,
-       IntlRelativeFormat = IntlRelativeFormatObj.default,
-       createFormatCache  = createFormatCacheObj.default;
+var Intl = window.Intl || IntlObj.default,
+    IntlMessageFormat = IntlMessageFormatObj.default,
+    IntlRelativeFormat = IntlRelativeFormatObj.default,
+    createFormatCache = createFormatCacheObj.default;
 
 /*extract locale*/
 var _locale = window.localStorage && localStorage.getItem('user_locale');
-if(!_locale) {
-       if(window.navigator) {
-               _locale = navigator.language || navigator.userLanguage;
+if (!_locale) {
+    if (window.navigator) {
+        _locale = navigator.language || navigator.userLanguage;
 
-               //For now removing the dashes from the language.
-               let indexOfDash = _locale.indexOf('-');
-               if(-1 !== indexOfDash) {
-                       _locale = _locale.substr(0, indexOfDash);
-               }
-       }
-       if(!_locale) {
-               _locale = 'en';
-       }
+        //For now removing the dashes from the language.
+        let indexOfDash = _locale.indexOf('-');
+        if (-1 !== indexOfDash) {
+            _locale = _locale.substr(0, indexOfDash);
+        }
+    }
+    if (!_locale) {
+        _locale = 'en';
+    }
 }
 
 var _localeUpper = _locale.toUpperCase();
 var i18n = {
+    _locale: _locale,
+    _localeUpper: _localeUpper,
+    _i18nData: i18nJson || {},
 
-       _locale: _locale,
-       _localeUpper: _localeUpper,
-       _i18nData: i18nJson || {},
+    number(num) {
+        return createFormatCache(Intl.NumberFormat)(this._locale).format(num);
+    },
 
-       number(num) {
-               return createFormatCache(Intl.NumberFormat)(this._locale).format(num);
-       },
+    date(date, options, relativeDates) {
+        if (undefined === relativeDates || relativeDates) {
+            return this.dateRelative(date, options);
+        } else {
+            return this.dateNormal(date, options);
+        }
+    },
 
-       date(date, options, relativeDates) {
-               if (undefined === relativeDates || relativeDates) {
-                       return this.dateRelative(date, options);
-               } else {
-                       return this.dateNormal(date, options);
-               }
-       },
-
-       dateNormal(date, options) {
-               return createFormatCache(Intl.DateTimeFormat)(this._locale, options).format(date);
-       },
-
-       dateRelative(date, options) {
-               return createFormatCache(IntlRelativeFormat)(this._locale, options).format(date);
-       },
-       message(messageId, options) {
-               let messageTxt = null;
-               if (i18nJson && i18nJson[messageId]) {
-                       messageTxt = i18nJson[messageId];
-               } else {
-                       messageTxt = String(messageId);
-               }
-               return createFormatCache(IntlMessageFormat)(messageTxt, this._locale).format(options);
-
-       },
-       getLocale() {
-               return this._locale;
-       },
-       getLocaleUpper() {
-               return this._localeUpper;
-       },
-       setLocale(locale) {
-               localStorage.setItem('user_locale', locale);
-               window.location.reload();
-       }
+    dateNormal(date, options) {
+        return createFormatCache(Intl.DateTimeFormat)(
+            this._locale,
+            options
+        ).format(date);
+    },
 
+    dateRelative(date, options) {
+        return createFormatCache(IntlRelativeFormat)(
+            this._locale,
+            options
+        ).format(date);
+    },
+    message(messageId, options) {
+        let messageTxt = null;
+        if (i18nJson && i18nJson[messageId]) {
+            messageTxt = i18nJson[messageId];
+        } else {
+            messageTxt = String(messageId);
+        }
+        return createFormatCache(IntlMessageFormat)(
+            messageTxt,
+            this._locale
+        ).format(options);
+    },
+    getLocale() {
+        return this._locale;
+    },
+    getLocaleUpper() {
+        return this._localeUpper;
+    },
+    setLocale(locale) {
+        localStorage.setItem('user_locale', locale);
+        window.location.reload();
+    }
 };
 function i18nWrapper() {
-       return i18nWrapper.message.apply(i18nWrapper, arguments);
+    return i18nWrapper.message.apply(i18nWrapper, arguments);
 }
 
 /*replace with some kind of extend method*/
 var prop, propKey;
 for (propKey in i18n) {
-       prop = i18n[propKey];
-       if (typeof prop === 'function') {
-               prop = prop.bind(i18nWrapper);
-       }
-       i18nWrapper[propKey] = prop;
+    prop = i18n[propKey];
+    if (typeof prop === 'function') {
+        prop = prop.bind(i18nWrapper);
+    }
+    i18nWrapper[propKey] = prop;
 }
 
 export default i18nWrapper;
index 816915b..79f9505 100644 (file)
@@ -1,35 +1,51 @@
 import React from 'react';
-import {storiesOf, action} from '@kadira/storybook';
-import {text, number} from '@kadira/storybook-addon-knobs';
-import {withKnobs} from '@kadira/storybook-addon-knobs';
+import { storiesOf } from '@kadira/storybook';
+import { withKnobs } from '@kadira/storybook-addon-knobs';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import i18nJson from 'nfvo-utils/i18n/en.json';
 
 const stories = storiesOf('i18n', module);
 stories.addDecorator(withKnobs);
 
-
 i18nJson['added'] = 'this is my test';
 i18nJson['added with {param}'] = 'this is my test with {param}';
 
-stories
-       .add('i18n tests', () => {
-               let keys = [
-                       'I do not exist',
-                       'Delete',
-                       'OrchestrationTemplateCandidate/File Structure'
-               ];
-               let translations = [];
-               let i=0;
-               translations.push(<div id={i++}>KEY: VALUE</div>)
-               keys.forEach((key) => {
-                       translations.push((<div id={i++}>{key} : {i18n(key)} </div>));
-               });
-               var param = 'param';
-               translations.push((<div id={i++}>added : {i18n('added')} </div>));
-               translations.push((<div id={i++}><font color="red"><b>WRONG</b></font> - added with ${param} in translation : {i18n(`added with ${param}`)} </div>));
-               translations.push((<div id={i++}><font color="green"><b>RIGHT</b></font> - added with ${param} and options object {JSON.stringify({param:param})}: {i18n('added with {param}', {param: param})} </div>));
+stories.add('i18n tests', () => {
+    let keys = [
+        'I do not exist',
+        'Delete',
+        'OrchestrationTemplateCandidate/File Structure'
+    ];
+    let translations = [];
+    let i = 0;
+    translations.push(<div id={i++}>KEY: VALUE</div>);
+    keys.forEach(key => {
+        translations.push(
+            <div id={i++}>
+                {key} : {i18n(key)}{' '}
+            </div>
+        );
+    });
+    var param = 'param';
+    translations.push(<div id={i++}>added : {i18n('added')} </div>);
+    translations.push(
+        <div id={i++}>
+            <font color="red">
+                <b>WRONG</b>
+            </font>{' '}
+            - added with ${param} in translation : {i18n(`added with ${param}`)}{' '}
+        </div>
+    );
+    translations.push(
+        <div id={i++}>
+            <font color="green">
+                <b>RIGHT</b>
+            </font>{' '}
+            - added with ${param} and options object{' '}
+            {JSON.stringify({ param: param })}:{' '}
+            {i18n('added with {param}', { param: param })}{' '}
+        </div>
+    );
 
-               return (<div>{translations}</div>);
-       })
-;
+    return <div>{translations}</div>;
+});
index f4c0d4e..66c67dd 100644 (file)
  * permissions and limitations under the License.
  */
 const JSONPointer = {
-
-       extractParentPointer(pointer) {
-               return pointer.replace(/\/[^\/]+$/, '');
-       },
-
-       extractLastPart(pointer) {
-               const [,lastPart] = pointer.match(/\/([^\/]+)$/) || [];
-               return lastPart;
-       },
-
-       extractParts(pointer = '') {
-               return pointer.split('/').slice(1)
-                       .map(part => part.replace(/~1/g, '/'))
-                       .map(part => part.replace(/~0/g, '~'));
-       },
-
-       getValue(object, pointer) {
-               let parts = JSONPointer.extractParts(pointer);
-               return parts.reduce((object, part) => object && object[part], object);
-       },
-
-       setValue(object, pointer, value) {
-               let clone = obj => Array.isArray(obj) ? [...obj] : {...obj};
-
-               let parts = JSONPointer.extractParts(pointer),
-                       newObject = clone(object),
-                       subObject = object,
-                       subNewObject = newObject;
-
-               for(let i = 0, n = parts.length - 1; i < n; ++i) {
-                       let nextSubObject = subObject && subObject[parts[i]];
-                       subNewObject = subNewObject[parts[i]] = nextSubObject ? clone(nextSubObject) : {};
-                       subObject = nextSubObject;
-               }
-               subNewObject[parts[parts.length - 1]] = value;
-
-               return newObject;
-       }
+    extractParentPointer(pointer) {
+        return pointer.replace(/\/[^\/]+$/, '');
+    },
+
+    extractLastPart(pointer) {
+        const [, lastPart] = pointer.match(/\/([^\/]+)$/) || [];
+        return lastPart;
+    },
+
+    extractParts(pointer = '') {
+        return pointer
+            .split('/')
+            .slice(1)
+            .map(part => part.replace(/~1/g, '/'))
+            .map(part => part.replace(/~0/g, '~'));
+    },
+
+    getValue(object, pointer) {
+        let parts = JSONPointer.extractParts(pointer);
+        return parts.reduce((object, part) => object && object[part], object);
+    },
+
+    setValue(object, pointer, value) {
+        let clone = obj => (Array.isArray(obj) ? [...obj] : { ...obj });
+
+        let parts = JSONPointer.extractParts(pointer),
+            newObject = clone(object),
+            subObject = object,
+            subNewObject = newObject;
+
+        for (let i = 0, n = parts.length - 1; i < n; ++i) {
+            let nextSubObject = subObject && subObject[parts[i]];
+            subNewObject = subNewObject[parts[i]] = nextSubObject
+                ? clone(nextSubObject)
+                : {};
+            subObject = nextSubObject;
+        }
+        subNewObject[parts[parts.length - 1]] = value;
+
+        return newObject;
+    }
 };
 
 export default JSONPointer;
index 3b3a9bf..53d288f 100644 (file)
@@ -18,235 +18,264 @@ import cloneDeep from 'lodash/cloneDeep.js';
 import JSONPointer from './JSONPointer.js';
 
 export default class JSONSchema {
-
-       setSchema(schema) {
-               this._schema = schema;
-               this._fragmentsCache = new Map();
-               // this._ajv = new Ajv({
-               //      useDefaults: true,
-               //      coerceTypes: true
-               // });
-               // this._validate = this._ajv.compile(schema);
-       }
-
-       processData(data) {
-               data = cloneDeep(data);
-               // this._validate(data);
-               return data;
-       }
-
-       // array of names of validation functions
-       setSupportedValidationFunctions(supportedValidationFunctions) {
-               this._supportedValidationFunctions = supportedValidationFunctions;
-       }
-
-       /* FYI - I was going to support "required" but then found out that server never sends it in its schema (it was a business decision. so leaving the code commented for now */
-       flattenSchema(supportedValidationFunctions) {
-               if (supportedValidationFunctions) { this.setSupportedValidationFunctions(supportedValidationFunctions); }
-               let genericFieldInfo = {};
-               if (this._schema && this._schema.properties) {
-                       this.travelProperties(this._schema.properties, genericFieldInfo/*, this._schema.required*/);
-               }
-               return {genericFieldInfo};
-       }
-
-       extractGenericFieldInfo(item) {
-               let validationsArr = [];
-               let additionalInfo = { isValid: true, errorText: ''};
-               for (let value in item) {
-                       if (this._supportedValidationFunctions.includes(value)) {
-                               let validationItem = this.extractValidations(item, value);
-                               validationsArr[validationsArr.length] = validationItem;
-                       } else {
-                               let enumResult = this.extractEnum(item, value);
-                               if (enumResult !== null) {
-                                       additionalInfo.enum = enumResult;
-                               }
-                               else {
-                                       additionalInfo[value] = item[value];
-                               }
-                               /*if (required.includes (property)) {
+    setSchema(schema) {
+        this._schema = schema;
+        this._fragmentsCache = new Map();
+        // this._ajv = new Ajv({
+        //     useDefaults: true,
+        //     coerceTypes: true
+        // });
+        // this._validate = this._ajv.compile(schema);
+    }
+
+    processData(data) {
+        data = cloneDeep(data);
+        // this._validate(data);
+        return data;
+    }
+
+    // array of names of validation functions
+    setSupportedValidationFunctions(supportedValidationFunctions) {
+        this._supportedValidationFunctions = supportedValidationFunctions;
+    }
+
+    /* FYI - I was going to support "required" but then found out that server never sends it in its schema (it was a business decision. so leaving the code commented for now */
+    flattenSchema(supportedValidationFunctions) {
+        if (supportedValidationFunctions) {
+            this.setSupportedValidationFunctions(supportedValidationFunctions);
+        }
+        let genericFieldInfo = {};
+        if (this._schema && this._schema.properties) {
+            this.travelProperties(
+                this._schema.properties,
+                genericFieldInfo /*, this._schema.required*/
+            );
+        }
+        return { genericFieldInfo };
+    }
+
+    extractGenericFieldInfo(item) {
+        let validationsArr = [];
+        let additionalInfo = { isValid: true, errorText: '' };
+        for (let value in item) {
+            if (this._supportedValidationFunctions.includes(value)) {
+                let validationItem = this.extractValidations(item, value);
+                validationsArr[validationsArr.length] = validationItem;
+            } else {
+                let enumResult = this.extractEnum(item, value);
+                if (enumResult !== null) {
+                    additionalInfo.enum = enumResult;
+                } else {
+                    additionalInfo[value] = item[value];
+                }
+                /*if (required.includes (property)) {
                                 additionalInfo[value].isRequired = true ;
                                 }*/
-                       }
-               }
-
-               additionalInfo.validations = validationsArr;
-               return additionalInfo;
-       }
-
-       extractValidations(item, value) {
-               let validationItem;
-               let data = item[value];
-               if (value === 'maximum') {
-                       if (item.exclusiveMaximum) {
-                               value = 'maximumExclusive';
-                       }
-               }
-               if (value === 'minimum') {
-                       if (item.exclusiveMinimum) {
-                               value = 'minimumExclusive';
-                       }
-               }
-               validationItem = {type: value, data: data};
-               return validationItem;
-       }
-
-       extractEnum(item, value) {
-               let enumResult = null;
-               if (value === 'type' && item[value] === 'array') {
-                       let items = item.items;
-                       if (items && items.enum && items.enum.length > 0) {
-                               let values = items.enum
-                                       .filter(value => value)
-                                       .map(value => ({enum: value, title: value}));
-                               enumResult = values;
-                       }
-               }
-               else if (value === 'enum') {
-                       let items = item[value];
-                       if (items && items.length > 0) {
-                               let values = items
-                                       .filter(value => value)
-                                       .map(value => ({enum: value, title: value}));
-                               enumResult = values;
-                       }
-               }
-               return enumResult;
-       }
-
-       travelProperties(properties, genericFieldDefs, /*required = [],*/ pointer = ''){
-               let newPointer = pointer;
-               for (let property in properties) {
-                       newPointer = newPointer ? newPointer + '/' + property : property;
-                       if (properties[property].properties) {
-                               this.travelProperties(properties[property].properties, genericFieldDefs /*, properties[property].required*/, newPointer);
-                       }
-                       else if (properties[property].$ref){
-                               let fragment = this._getSchemaFragmentByRef(properties[property].$ref);
-                               if (fragment.properties) {
-                                       this.travelProperties(fragment.properties, genericFieldDefs /*, properties[property].required*/, newPointer);
-                               } else {
-                                       genericFieldDefs[newPointer] = this.extractGenericFieldInfo(fragment.properties);
-                               }
-                       }
-                       else {
-                               genericFieldDefs[newPointer] = this.extractGenericFieldInfo(properties[property]);
-                       }
-                       newPointer = pointer;
-               }
-       }
-
-       getTitle(pointer) {
-               return this._getSchemaFragment(pointer).title;
-       }
-
-       exists(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return !!fragment;
-       }
-
-       getDefault(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.default;
-       }
-
-       getEnum(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && (fragment.type === 'array' ? fragment.items.enum : fragment.enum);
-       }
-
-       isRequired(pointer) {
-               const parentPointer = JSONPointer.extractParentPointer(pointer);
-               const lastPart = JSONPointer.extractLastPart(pointer);
-               let parentFragment = this._getSchemaFragment(parentPointer);
-               return parentFragment && parentFragment.required && parentFragment.required.includes(lastPart);
-       }
-
-       isNumber(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.type === 'number';
-       }
-
-       getMaxValue(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.exclusiveMaximum ? fragment.maximum - 1 : fragment.maximum;
-       }
-
-       getMinValue(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.exclusiveMinimum ? fragment.minimum : fragment.minimum;
-       }
-
-       isString(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.type === 'string';
-       }
-
-       getPattern(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.pattern;
-       }
-
-       getMaxLength(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.maxLength;
-       }
-
-       getMinLength(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.minLength;
-       }
-
-       isArray(pointer) {
-               const fragment = this._getSchemaFragment(pointer);
-               return fragment && fragment.type === 'array';
-       }
-
-       _getSchemaFragment(pointer) {
-               if (this._fragmentsCache.has(pointer)) {
-                       return this._fragmentsCache.get(pointer);
-               }
-
-               let parts = JSONPointer.extractParts(pointer);
-
-               let fragment = parts.reduce((fragment, part) => {
-                       if (fragment === undefined) {
-                               return undefined;
-                       }
-
-                       if (fragment.$ref) {
-                               fragment = this._getSchemaFragmentByRef(fragment.$ref);
-                       }
-
-                       switch (fragment.type) {
-                               case 'object':
-                                       return fragment.properties && fragment.properties[part];
-
-                               case 'array':
-                                       return fragment.enum && fragment.enum[part];
-
-                               default:
-                                       // throw new Error(`Incorrect/unsupported JSONPointer "${pointer}" from "${part}"`);
-                                       return undefined;
-                       }
-               }, this._schema);
-
-               while(fragment && fragment.$ref) {
-                       fragment = this._getSchemaFragmentByRef(fragment.$ref);
-               }
-
-               this._fragmentsCache.set(pointer, fragment);
-               return fragment;
-       }
-
-       _getSchemaFragmentByRef($ref) {
-               let pointer = $ref.substr(1);
-               return JSONPointer.getValue(this._schema, pointer);
-               // let fragmentAjv = new Ajv();
-               // fragmentAjv.addSchema(this._schema);
-               // let compiledFragment = fragmentAjv.compile({$ref});
-               // let fragment = compiledFragment.refVal[compiledFragment.refs[$ref]];
-               // return fragment;
-       }
-};
+            }
+        }
+
+        additionalInfo.validations = validationsArr;
+        return additionalInfo;
+    }
+
+    extractValidations(item, value) {
+        let validationItem;
+        let data = item[value];
+        if (value === 'maximum') {
+            if (item.exclusiveMaximum) {
+                value = 'maximumExclusive';
+            }
+        }
+        if (value === 'minimum') {
+            if (item.exclusiveMinimum) {
+                value = 'minimumExclusive';
+            }
+        }
+        validationItem = { type: value, data: data };
+        return validationItem;
+    }
+
+    extractEnum(item, value) {
+        let enumResult = null;
+        if (value === 'type' && item[value] === 'array') {
+            let items = item.items;
+            if (items && items.enum && items.enum.length > 0) {
+                let values = items.enum
+                    .filter(value => value)
+                    .map(value => ({ enum: value, title: value }));
+                enumResult = values;
+            }
+        } else if (value === 'enum') {
+            let items = item[value];
+            if (items && items.length > 0) {
+                let values = items
+                    .filter(value => value)
+                    .map(value => ({ enum: value, title: value }));
+                enumResult = values;
+            }
+        }
+        return enumResult;
+    }
+
+    travelProperties(
+        properties,
+        genericFieldDefs,
+        /*required = [],*/ pointer = ''
+    ) {
+        let newPointer = pointer;
+        for (let property in properties) {
+            newPointer = newPointer ? newPointer + '/' + property : property;
+            if (properties[property].properties) {
+                this.travelProperties(
+                    properties[property].properties,
+                    genericFieldDefs /*, properties[property].required*/,
+                    newPointer
+                );
+            } else if (properties[property].$ref) {
+                let fragment = this._getSchemaFragmentByRef(
+                    properties[property].$ref
+                );
+                if (fragment.properties) {
+                    this.travelProperties(
+                        fragment.properties,
+                        genericFieldDefs /*, properties[property].required*/,
+                        newPointer
+                    );
+                } else {
+                    genericFieldDefs[newPointer] = this.extractGenericFieldInfo(
+                        fragment.properties
+                    );
+                }
+            } else {
+                genericFieldDefs[newPointer] = this.extractGenericFieldInfo(
+                    properties[property]
+                );
+            }
+            newPointer = pointer;
+        }
+    }
+
+    getTitle(pointer) {
+        return this._getSchemaFragment(pointer).title;
+    }
+
+    exists(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return !!fragment;
+    }
+
+    getDefault(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.default;
+    }
+
+    getEnum(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return (
+            fragment &&
+            (fragment.type === 'array' ? fragment.items.enum : fragment.enum)
+        );
+    }
+
+    isRequired(pointer) {
+        const parentPointer = JSONPointer.extractParentPointer(pointer);
+        const lastPart = JSONPointer.extractLastPart(pointer);
+        let parentFragment = this._getSchemaFragment(parentPointer);
+        return (
+            parentFragment &&
+            parentFragment.required &&
+            parentFragment.required.includes(lastPart)
+        );
+    }
+
+    isNumber(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.type === 'number';
+    }
+
+    getMaxValue(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.exclusiveMaximum
+            ? fragment.maximum - 1
+            : fragment.maximum;
+    }
+
+    getMinValue(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.exclusiveMinimum
+            ? fragment.minimum
+            : fragment.minimum;
+    }
+
+    isString(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.type === 'string';
+    }
+
+    getPattern(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.pattern;
+    }
+
+    getMaxLength(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.maxLength;
+    }
+
+    getMinLength(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.minLength;
+    }
+
+    isArray(pointer) {
+        const fragment = this._getSchemaFragment(pointer);
+        return fragment && fragment.type === 'array';
+    }
+
+    _getSchemaFragment(pointer) {
+        if (this._fragmentsCache.has(pointer)) {
+            return this._fragmentsCache.get(pointer);
+        }
+
+        let parts = JSONPointer.extractParts(pointer);
+
+        let fragment = parts.reduce((fragment, part) => {
+            if (fragment === undefined) {
+                return undefined;
+            }
+
+            if (fragment.$ref) {
+                fragment = this._getSchemaFragmentByRef(fragment.$ref);
+            }
+
+            switch (fragment.type) {
+                case 'object':
+                    return fragment.properties && fragment.properties[part];
+
+                case 'array':
+                    return fragment.enum && fragment.enum[part];
+
+                default:
+                    // throw new Error(`Incorrect/unsupported JSONPointer "${pointer}" from "${part}"`);
+                    return undefined;
+            }
+        }, this._schema);
+
+        while (fragment && fragment.$ref) {
+            fragment = this._getSchemaFragmentByRef(fragment.$ref);
+        }
+
+        this._fragmentsCache.set(pointer, fragment);
+        return fragment;
+    }
+
+    _getSchemaFragmentByRef($ref) {
+        let pointer = $ref.substr(1);
+        return JSONPointer.getValue(this._schema, pointer);
+        // let fragmentAjv = new Ajv();
+        // fragmentAjv.addSchema(this._schema);
+        // let compiledFragment = fragmentAjv.compile({$ref});
+        // let fragment = compiledFragment.refVal[compiledFragment.refs[$ref]];
+        // return fragment;
+    }
+}
index b415dd7..89e9f40 100644 (file)
@@ -14,5 +14,7 @@
  * permissions and limitations under the License.
  */
 export default function sortByStringProperty(array, property) {
-       return [...array].sort((a, b) => a[property].toLowerCase().localeCompare(b[property].toLowerCase()));
+    return [...array].sort((a, b) =>
+        a[property].toLowerCase().localeCompare(b[property].toLowerCase())
+    );
 }
index bafef7d..bca750a 100644 (file)
  * limitations under the License.
  */
 
-import {createStore, applyMiddleware, compose} from 'redux';
+import { createStore, applyMiddleware, compose } from 'redux';
 import Reducers from './Reducers.js';
 const thunk = store => next => action =>
-       typeof action === 'function' ?
-               action(store.dispatch, store.getState) :
-               next(action);
-
+    typeof action === 'function'
+        ? action(store.dispatch, store.getState)
+        : next(action);
 
 const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
-export const storeCreator = (initialState) => createStore(Reducers, initialState, composeEnhancers(applyMiddleware(thunk)));
-
+export const storeCreator = initialState =>
+    createStore(
+        Reducers,
+        initialState,
+        composeEnhancers(applyMiddleware(thunk))
+    );
 
 const store = storeCreator();
 
 if (module.hot) {
-       module.hot.accept('./Reducers.js', () =>
-               store.replaceReducer(require('./Reducers.js').default)
-       );
+    module.hot.accept('./Reducers.js', () =>
+        store.replaceReducer(require('./Reducers.js').default)
+    );
 }
 
 export default store;
index aa81eb3..abebb6d 100644 (file)
@@ -15,7 +15,7 @@
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import {Provider} from 'react-redux';
+import { Provider } from 'react-redux';
 import GlobalModal from 'nfvo-components/modal/GlobalModal.js';
 import Loader from 'nfvo-components/loader/Loader.jsx';
 import WebSocketUtil from 'nfvo-utils/WebSocketUtil.js';
@@ -24,31 +24,32 @@ import store from './AppStore.js';
 import FeaturesActionHelper from 'sdc-app/features/FeaturesActionHelper.js';
 
 class Application extends React.Component {
-       static propTypes = {
-               openSocket: PropTypes.bool
-       };
-       componentDidMount() {
-               const {openSocket = true} = this.props;
-               if(openSocket) {
-                       UserNotificationsActionHelper.notificationsFirstHandling(store.dispatch);
-               }
-               FeaturesActionHelper.getFeaturesList(store.dispatch);
-       }
-       componentWillUnmount() {
-               WebSocketUtil.close();
-       }
-       render() {
-               return (
-                       <Provider store={store}>
-                               <div>
-                                       <GlobalModal/>
-                                       {this.props.children}
-                                       <Loader />
-                               </div>
-                       </Provider>
-               );
-       }
+    static propTypes = {
+        openSocket: PropTypes.bool
+    };
+    componentDidMount() {
+        const { openSocket = true } = this.props;
+        if (openSocket) {
+            UserNotificationsActionHelper.notificationsFirstHandling(
+                store.dispatch
+            );
+        }
+        FeaturesActionHelper.getFeaturesList(store.dispatch);
+    }
+    componentWillUnmount() {
+        WebSocketUtil.close();
+    }
+    render() {
+        return (
+            <Provider store={store}>
+                <div>
+                    <GlobalModal />
+                    {this.props.children}
+                    <Loader />
+                </div>
+            </Provider>
+        );
+    }
 }
 
 export default Application;
-
index 28fab80..63296b5 100644 (file)
@@ -15,7 +15,7 @@
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
 
 import LicenseModelActionHelper from './onboarding/licenseModel/LicenseModelActionHelper.js';
@@ -27,140 +27,198 @@ import LicenseKeyGroupsListEditor from './onboarding/licenseModel/licenseKeyGrou
 import LicenseKeyGroupsActionHelper from './onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
 import EntitlementPoolsListEditor from './onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js';
 import EntitlementPoolsActionHelper from './onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
-import SoftwareProductLandingPage  from './onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js';
-import SoftwareProductDetails  from './onboarding/softwareProduct/details/SoftwareProductDetails.js';
+import SoftwareProductLandingPage from './onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js';
+import SoftwareProductDetails from './onboarding/softwareProduct/details/SoftwareProductDetails.js';
 import Onboard from './onboarding/onboard/Onboard.js';
 import SoftwareProductActionHelper from './onboarding/softwareProduct/SoftwareProductActionHelper.js';
 import FlowsListEditor from './flows/FlowsListEditor.js';
 import FlowsActions from './flows/FlowsActions.js';
 
-
-const mapStateToProps = ({licenseModelList}) => {
-       return {licenseModelList};
+const mapStateToProps = ({ licenseModelList }) => {
+    return { licenseModelList };
 };
 
-
 const mapActionsToProps = dispatch => {
-       return {
-               onBootstrapped: () => LicenseModelActionHelper.fetchLicenseModels(dispatch),
-               onLicenseAgreementListEditor: licenseModelId => LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId}),
-               onFeatureGroupsListEditor: licenseModelId => FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId}),
-               onLicenseKeyGroupsListEditor: licenseModelId =>LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId}),
-               onEntitlementPoolsListEditor: licenseModelId => EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId}),
-               onOnboardingCatalog: () => SoftwareProductActionHelper.fetchSoftwareProductList(dispatch),
-               onSoftwareProductDetails: () => SoftwareProductActionHelper.fetchSoftwareProductCategories(dispatch),
-               onFlowsListEditor: () => FlowsActions.fetchFlows(dispatch)
-       };
+    return {
+        onBootstrapped: () =>
+            LicenseModelActionHelper.fetchLicenseModels(dispatch),
+        onLicenseAgreementListEditor: licenseModelId =>
+            LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
+                licenseModelId
+            }),
+        onFeatureGroupsListEditor: licenseModelId =>
+            FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+                licenseModelId
+            }),
+        onLicenseKeyGroupsListEditor: licenseModelId =>
+            LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {
+                licenseModelId
+            }),
+        onEntitlementPoolsListEditor: licenseModelId =>
+            EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {
+                licenseModelId
+            }),
+        onOnboardingCatalog: () =>
+            SoftwareProductActionHelper.fetchSoftwareProductList(dispatch),
+        onSoftwareProductDetails: () =>
+            SoftwareProductActionHelper.fetchSoftwareProductCategories(
+                dispatch
+            ),
+        onFlowsListEditor: () => FlowsActions.fetchFlows(dispatch)
+    };
 };
 
 class ModuleOptions extends React.Component {
+    static propTypes = {
+        onBootstrapped: PropTypes.func.isRequired,
+        onLicenseAgreementListEditor: PropTypes.func.isRequired,
+        onFeatureGroupsListEditor: PropTypes.func.isRequired,
+        onLicenseKeyGroupsListEditor: PropTypes.func.isRequired,
+        onEntitlementPoolsListEditor: PropTypes.func.isRequired,
+        onOnboardingCatalog: PropTypes.func.isRequired,
+        onSoftwareProductDetails: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               onBootstrapped: PropTypes.func.isRequired,
-               onLicenseAgreementListEditor: PropTypes.func.isRequired,
-               onFeatureGroupsListEditor: PropTypes.func.isRequired,
-               onLicenseKeyGroupsListEditor: PropTypes.func.isRequired,
-               onEntitlementPoolsListEditor: PropTypes.func.isRequired,
-               onOnboardingCatalog: PropTypes.func.isRequired,
-               onSoftwareProductDetails: PropTypes.func.isRequired,
-       };
-
-       state = {
-               currentModule: localStorage.getItem('default-module'),
-               licenseModelId: localStorage.getItem('default-license-model-id')
-       };
+    state = {
+        currentModule: localStorage.getItem('default-module'),
+        licenseModelId: localStorage.getItem('default-license-model-id')
+    };
 
-       componentDidMount() {
-               this.props.onBootstrapped();
-       }
+    componentDidMount() {
+        this.props.onBootstrapped();
+    }
 
-       render() {
-               let {currentModule, licenseModelId} = this.state;
-               let {licenseModelList} = this.props;
-               return (
-                       <div style={{marginTop:20}}>
-                               <Input
-                                       name='licenseModel'
-                                       value={licenseModelId}
-                                       ref='licenseModelId'
-                                       type='select'
-                                       onChange={this.handleLicenseModelIdChange}
-                                       className='inner-pagination select-input'>
-                                       <option value='' key={null}>Select License Model</option>
-                                       {
-                                               licenseModelList.map(({id, vendorName}) => <option value={id} key={id}>{`${vendorName} License Model`}</option>)
-                                       }
-                               </Input>
-                               <Input
-                                       name='currentView'
-                                       value={currentModule}
-                                       ref='selectedModule'
-                                       type='select'
-                                       onChange={this.handleModuleSelection}
-                                       className='inner-pagination select-input'>
-                                       <option value=''>Select Module</option>
-                                       <option value='EntitlementPoolsListEditor'>Entitlement Pools</option>
-                                       <option value='LicenseAgreementListEditor'>License Agreements</option>
-                                       <option value='FutureGroupListEditor'>Feature Groups</option>
-                                       <option value='LicenseKeyGroupsListEditor'>License Key Groups</option>
-                                       <option value='SoftwareProductLanding'>Software Product Landing</option>
-                                       <option value='SoftwareProductDetails'>Software Product Details</option>
-                                       <option value='OnboardingCatalog'>Onboarding Catalog</option>
-                                       <option value='Flows'>Flows</option>
-                               </Input>
-                               <div className='sub-module-view' style={{paddingTop: 10, margin: 4, borderTop: '1px solid silver'}}>
-                                       {this.renderModule(currentModule)}
-                               </div>
-                       </div>
-               );
-       }
+    render() {
+        let { currentModule, licenseModelId } = this.state;
+        let { licenseModelList } = this.props;
+        return (
+            <div style={{ marginTop: 20 }}>
+                <Input
+                    name="licenseModel"
+                    value={licenseModelId}
+                    ref="licenseModelId"
+                    type="select"
+                    onChange={this.handleLicenseModelIdChange}
+                    className="inner-pagination select-input">
+                    <option value="" key={null}>
+                        Select License Model
+                    </option>
+                    {licenseModelList.map(({ id, vendorName }) => (
+                        <option
+                            value={id}
+                            key={id}>{`${vendorName} License Model`}</option>
+                    ))}
+                </Input>
+                <Input
+                    name="currentView"
+                    value={currentModule}
+                    ref="selectedModule"
+                    type="select"
+                    onChange={this.handleModuleSelection}
+                    className="inner-pagination select-input">
+                    <option value="">Select Module</option>
+                    <option value="EntitlementPoolsListEditor">
+                        Entitlement Pools
+                    </option>
+                    <option value="LicenseAgreementListEditor">
+                        License Agreements
+                    </option>
+                    <option value="FutureGroupListEditor">
+                        Feature Groups
+                    </option>
+                    <option value="LicenseKeyGroupsListEditor">
+                        License Key Groups
+                    </option>
+                    <option value="SoftwareProductLanding">
+                        Software Product Landing
+                    </option>
+                    <option value="SoftwareProductDetails">
+                        Software Product Details
+                    </option>
+                    <option value="OnboardingCatalog">
+                        Onboarding Catalog
+                    </option>
+                    <option value="Flows">Flows</option>
+                </Input>
+                <div
+                    className="sub-module-view"
+                    style={{
+                        paddingTop: 10,
+                        margin: 4,
+                        borderTop: '1px solid silver'
+                    }}>
+                    {this.renderModule(currentModule)}
+                </div>
+            </div>
+        );
+    }
 
-       renderModule(currentModule) {
-               const {licenseModelId} = this.state;
-               if (!licenseModelId) {
-                       return;
-               }
+    renderModule(currentModule) {
+        const { licenseModelId } = this.state;
+        if (!licenseModelId) {
+            return;
+        }
 
-               switch (currentModule) {
-                       case 'LicenseAgreementListEditor':
-                               this.props.onLicenseAgreementListEditor(licenseModelId);
-                               return <LicenseAgreementListEditor licenseModelId={licenseModelId}/>;
-                       case 'FutureGroupListEditor':
-                               this.props.onFeatureGroupsListEditor(licenseModelId);
-                               return <FeatureGroupListEditor licenseModelId={licenseModelId}/>;
-                       case 'EntitlementPoolsListEditor':
-                               this.props.onEntitlementPoolsListEditor(licenseModelId);
-                               return <EntitlementPoolsListEditor licenseModelId={licenseModelId}/>;
-                       case 'LicenseKeyGroupsListEditor':
-                               this.props.onLicenseKeyGroupsListEditor(licenseModelId);
-                               return <LicenseKeyGroupsListEditor licenseModelId={licenseModelId}/>;
-                       case 'SoftwareProductLanding':
-                               return <SoftwareProductLandingPage licenseModelId={licenseModelId}/>;
-                       case 'SoftwareProductDetails':
-                               this.props.onSoftwareProductDetails(licenseModelId);
-                               return <SoftwareProductDetails licenseModelId={licenseModelId}/>;
-                       case 'OnboardingCatalog':
-                               this.props.onOnboardingCatalog();
-                               return <Onboard/>;
-                       case 'Flows':
-                               this.props.onFlowsListEditor();
-                               return <FlowsListEditor/>;
-                       default:
-                               return;
-               }
-       }
+        switch (currentModule) {
+            case 'LicenseAgreementListEditor':
+                this.props.onLicenseAgreementListEditor(licenseModelId);
+                return (
+                    <LicenseAgreementListEditor
+                        licenseModelId={licenseModelId}
+                    />
+                );
+            case 'FutureGroupListEditor':
+                this.props.onFeatureGroupsListEditor(licenseModelId);
+                return (
+                    <FeatureGroupListEditor licenseModelId={licenseModelId} />
+                );
+            case 'EntitlementPoolsListEditor':
+                this.props.onEntitlementPoolsListEditor(licenseModelId);
+                return (
+                    <EntitlementPoolsListEditor
+                        licenseModelId={licenseModelId}
+                    />
+                );
+            case 'LicenseKeyGroupsListEditor':
+                this.props.onLicenseKeyGroupsListEditor(licenseModelId);
+                return (
+                    <LicenseKeyGroupsListEditor
+                        licenseModelId={licenseModelId}
+                    />
+                );
+            case 'SoftwareProductLanding':
+                return (
+                    <SoftwareProductLandingPage
+                        licenseModelId={licenseModelId}
+                    />
+                );
+            case 'SoftwareProductDetails':
+                this.props.onSoftwareProductDetails(licenseModelId);
+                return (
+                    <SoftwareProductDetails licenseModelId={licenseModelId} />
+                );
+            case 'OnboardingCatalog':
+                this.props.onOnboardingCatalog();
+                return <Onboard />;
+            case 'Flows':
+                this.props.onFlowsListEditor();
+                return <FlowsListEditor />;
+            default:
+                return;
+        }
+    }
 
-       handleModuleSelection = () => {
-               let selectedModule = this.refs.selectedModule.getValue();
-               localStorage.setItem('default-module', selectedModule);
-               this.setState({currentModule: selectedModule});
-       }
+    handleModuleSelection = () => {
+        let selectedModule = this.refs.selectedModule.getValue();
+        localStorage.setItem('default-module', selectedModule);
+        this.setState({ currentModule: selectedModule });
+    };
 
-       handleLicenseModelIdChange = () => {
-               let licenseModelId = this.refs.licenseModelId.getValue();
-               localStorage.setItem('default-license-model-id', licenseModelId);
-               this.setState({licenseModelId});
-       }
+    handleLicenseModelIdChange = () => {
+        let licenseModelId = this.refs.licenseModelId.getValue();
+        localStorage.setItem('default-license-model-id', licenseModelId);
+        this.setState({ licenseModelId });
+    };
 }
 
 export default connect(mapStateToProps, mapActionsToProps)(ModuleOptions);
index a0a8eba..9f42423 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import {combineReducers} from 'redux';
+import { combineReducers } from 'redux';
 import onBoardingReducersMap from './onboarding/OnboardingReducersMap.js';
 import flowsReducersMap from './flows/FlowsReducersMap.js';
 import loaderReducer from 'nfvo-components/loader/LoaderReducer.js';
@@ -22,12 +22,12 @@ import globalModalReducer from 'nfvo-components/modal/GlobalModalReducer.js';
 import notificationsReducer from 'sdc-app/onboarding/userNotifications/NotificationsReducer.js';
 
 export default combineReducers({
-       // on-boarding reducers
-       ...onBoardingReducersMap,
+    // on-boarding reducers
+    ...onBoardingReducersMap,
 
-       // flows reducers
-       ...flowsReducersMap,
-       modal: globalModalReducer,
-       loader: loaderReducer,
-       notifications: notificationsReducer
+    // flows reducers
+    ...flowsReducersMap,
+    modal: globalModalReducer,
+    loader: loaderReducer,
+    notifications: notificationsReducer
 });
index a1ad437..2978cac 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ActivityLogView from './ActivityLogView.jsx';
 
-export const mapStateToProps = ({users: {usersList}, licenseModel: {activityLog}}) => {
-
-       let activities = activityLog;
-       return {
-               activities: activities.map(activity => ({...activity, user: {id: activity.user, name: usersList.find(userObject => userObject.userId === activity.user).fullName}})),
-               usersList
-       };
+export const mapStateToProps = ({
+    users: { usersList },
+    licenseModel: { activityLog }
+}) => {
+    let activities = activityLog;
+    return {
+        activities: activities.map(activity => ({
+            ...activity,
+            user: {
+                id: activity.user,
+                name: usersList.find(
+                    userObject => userObject.userId === activity.user
+                ).fullName
+            }
+        })),
+        usersList
+    };
 };
 
-export default connect(mapStateToProps, undefined, null, {withRef: true})(ActivityLogView);
+export default connect(mapStateToProps, undefined, null, { withRef: true })(
+    ActivityLogView
+);
index 729d8fb..6856b08 100644 (file)
@@ -17,8 +17,13 @@ import ActivityLogConstants from './ActivityLogConstants.js';
 import ItemHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 export default {
-
-       fetchActivityLog(dispatch, {itemId, versionId}){
-               return ItemHelper.fetchActivityLog({itemId, versionId}).then(response => dispatch({type: ActivityLogConstants.ACTIVITY_LOG_UPDATED, response}));
-       }
+    fetchActivityLog(dispatch, { itemId, versionId }) {
+        return ItemHelper.fetchActivityLog({ itemId, versionId }).then(
+            response =>
+                dispatch({
+                    type: ActivityLogConstants.ACTIVITY_LOG_UPDATED,
+                    response
+                })
+        );
+    }
 };
index 69faf7c..2da3c77 100644 (file)
@@ -16,8 +16,5 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export default keyMirror({
-
-       ACTIVITY_LOG_UPDATED: null
-
+    ACTIVITY_LOG_UPDATED: null
 });
-
index fc3dfa1..418a9b9 100644 (file)
 import ActivityLogConstants from './ActivityLogConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case ActivityLogConstants.ACTIVITY_LOG_UPDATED:
-                       return [...action.response.results];
-       }
+    switch (action.type) {
+        case ActivityLogConstants.ACTIVITY_LOG_UPDATED:
+            return [...action.response.results];
+    }
 
-       return state;
+    return state;
 };
index 5b8c29b..d65e667 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
@@ -21,108 +21,177 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import LogDetails from './LogixUtil.jsx';
 
-function ActivityLogSortableCellHeader({isHeader, data, isDes, onSort}) {
-       //TODO check icon sdc-ui
-       if (isHeader) {
-               return (
-                       <span className='date-header' onClick={onSort}>
-                               <span>{data}</span>
-                               <span className={`header-sort-arrow ${isDes ? 'up' : 'down'}`}></span>
-                       </span>
-               );
-       }
-       return (
-               <span className='date-cell'>
-                       <span>{i18n.dateNormal(data, {
-                               year: 'numeric', month: 'numeric', day: 'numeric'
-                       })}</span>
-                       <span>{i18n.dateNormal(data, {
-                               hour: 'numeric', minute: 'numeric',
-                               hour12: true
-                       })}</span>
-               </span>
-       );
+function ActivityLogSortableCellHeader({ isHeader, data, isDes, onSort }) {
+    //TODO check icon sdc-ui
+    if (isHeader) {
+        return (
+            <span className="date-header" onClick={onSort}>
+                <span>{data}</span>
+                <span
+                    className={`header-sort-arrow ${isDes ? 'up' : 'down'}`}
+                />
+            </span>
+        );
+    }
+    return (
+        <span className="date-cell">
+            <span>
+                {i18n.dateNormal(data, {
+                    year: 'numeric',
+                    month: 'numeric',
+                    day: 'numeric'
+                })}
+            </span>
+            <span>
+                {i18n.dateNormal(data, {
+                    hour: 'numeric',
+                    minute: 'numeric',
+                    hour12: true
+                })}
+            </span>
+        </span>
+    );
 }
 
-function ActivityLogStatus({status, isHeader}) {
-       if (isHeader) {
-               return <span>{status}</span>;
-       }
-       let {message, success} = status;
-       return (
-               <span>
-                       <span className={`status-icon ${success}`}>{`${success ? i18n('Success') : i18n('Failure')}`}</span>
-                       {success && <SVGIcon name='checkCircle' color='positive'/>}
-                       {!success && <OverlayTrigger placement='bottom' overlay={<Tooltip className='activity-log-message-tooltip' id={'activity-log-message-tooltip'}>
-                               <div className='message-block'>{message}</div>
-                       </Tooltip>}>
-                               <span className='message-further-info-icon'>{'?'}</span>
-                       </OverlayTrigger>}
-               </span>
-       );
+function ActivityLogStatus({ status, isHeader }) {
+    if (isHeader) {
+        return <span>{status}</span>;
+    }
+    let { message, success } = status;
+    return (
+        <span>
+            <span className={`status-icon ${success}`}>{`${
+                success ? i18n('Success') : i18n('Failure')
+            }`}</span>
+            {success && <SVGIcon name="checkCircle" color="positive" />}
+            {!success && (
+                <OverlayTrigger
+                    placement="bottom"
+                    overlay={
+                        <Tooltip
+                            className="activity-log-message-tooltip"
+                            id={'activity-log-message-tooltip'}>
+                            <div className="message-block">{message}</div>
+                        </Tooltip>
+                    }>
+                    <span className="message-further-info-icon">{'?'}</span>
+                </OverlayTrigger>
+            )}
+        </span>
+    );
 }
 
-export function ActivityListItem({activity, isHeader, isDes, onSort}) {
-       let {type, timestamp, comment, user, status} = activity;
-       return (
-               <li className={`activity-list-item ${isHeader ? 'header' : ''}`} data-test-id='activity-list-item'>
-                       <div className='table-cell activity-date' data-test-id='activity-date'><ActivityLogSortableCellHeader isHeader={isHeader} data={timestamp} isDes={isDes} onSort={onSort}/></div>
-                       <div className='table-cell activity-action' data-test-id='activity-action'>{i18n(type)}</div>
-                       <div className='table-cell activity-comment' title={isHeader ? '' : comment} data-test-id='activity-comment'><span>{i18n(comment)}</span></div>
-                       <div className='table-cell activity-username' data-test-id='activity-username'>{isHeader ? i18n(activity.user) : `${i18n(user.name)} (${user.id})`}</div>
-                       <div className='table-cell activity-status' data-test-id='activity-status'><ActivityLogStatus isHeader={isHeader} status={status}/></div>
-               </li>
-       );
+export function ActivityListItem({ activity, isHeader, isDes, onSort }) {
+    let { type, timestamp, comment, user, status } = activity;
+    return (
+        <li
+            className={`activity-list-item ${isHeader ? 'header' : ''}`}
+            data-test-id="activity-list-item">
+            <div
+                className="table-cell activity-date"
+                data-test-id="activity-date">
+                <ActivityLogSortableCellHeader
+                    isHeader={isHeader}
+                    data={timestamp}
+                    isDes={isDes}
+                    onSort={onSort}
+                />
+            </div>
+            <div
+                className="table-cell activity-action"
+                data-test-id="activity-action">
+                {i18n(type)}
+            </div>
+            <div
+                className="table-cell activity-comment"
+                title={isHeader ? '' : comment}
+                data-test-id="activity-comment">
+                <span>{i18n(comment)}</span>
+            </div>
+            <div
+                className="table-cell activity-username"
+                data-test-id="activity-username">
+                {isHeader
+                    ? i18n(activity.user)
+                    : `${i18n(user.name)} (${user.id})`}
+            </div>
+            <div
+                className="table-cell activity-status"
+                data-test-id="activity-status">
+                <ActivityLogStatus isHeader={isHeader} status={status} />
+            </div>
+        </li>
+    );
 }
 
 class ActivityLogView extends Component {
+    state = {
+        localFilter: '',
+        sortDescending: true
+    };
 
-       state = {
-               localFilter: '',
-               sortDescending: true
-       };
+    render() {
+        return (
+            <div className="activity-log-view">
+                <LogDetails display={this.state.localFilter} />
+                <ListEditorView
+                    title={i18n('Activity Log')}
+                    filterValue={this.state.localFilter}
+                    onFilter={filter => this.setState({ localFilter: filter })}>
+                    <ActivityListItem
+                        activity={{
+                            timestamp: 'Date',
+                            type: 'Action',
+                            comment: 'Comment',
+                            user: 'Username',
+                            status: 'Status'
+                        }}
+                        isDes={this.state.sortDescending}
+                        onSort={() =>
+                            this.setState({
+                                sortDescending: !this.state.sortDescending
+                            })
+                        }
+                        isHeader
+                    />
+                    {this.sortActivities(
+                        this.filterActivities(),
+                        this.state.sortDescending
+                    ).map(activity => (
+                        <ActivityListItem
+                            key={activity.id}
+                            activity={activity}
+                        />
+                    ))}
+                </ListEditorView>
+            </div>
+        );
+    }
 
-       render() {
-               return (
-                       <div className='activity-log-view'>
-                               <LogDetails display={this.state.localFilter}/>
-                               <ListEditorView
-                                       title={i18n('Activity Log')}
-                                       filterValue={this.state.localFilter}
-                                       onFilter={filter => this.setState({localFilter: filter})}>
-                                       <ActivityListItem
-                                               activity={{timestamp: 'Date', type: 'Action', comment: 'Comment', user: 'Username', status: 'Status'}}
-                                               isDes={this.state.sortDescending}
-                                               onSort={() => this.setState({sortDescending: !this.state.sortDescending})}
-                                               isHeader/>
-                                       {this.sortActivities(this.filterActivities(), this.state.sortDescending).map(activity => <ActivityListItem key={activity.id} activity={activity}/>)}
-                               </ListEditorView>
-                       </div>
-               );
-       }
-
-       filterActivities() {
-               let {activities} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return activities.filter(({user = {id: '', name: ''}, comment = '', type = ''}) =>
-                       escape(user.id).match(filter) || escape(user.name).match(filter) || escape(comment).match(filter) || escape(type).match(filter));
-               }
-               else {
-                       return activities;
-               }
-       }
-
-       sortActivities(activities) {
-               if (this.state.sortDescending) {
-                       return activities.sort((a, b) => a.timestamp - b.timestamp);
-               }
-               else {
-                       return activities.reverse();
-               }
-       }
+    filterActivities() {
+        let { activities } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return activities.filter(
+                ({ user = { id: '', name: '' }, comment = '', type = '' }) =>
+                    escape(user.id).match(filter) ||
+                    escape(user.name).match(filter) ||
+                    escape(comment).match(filter) ||
+                    escape(type).match(filter)
+            );
+        } else {
+            return activities;
+        }
+    }
 
+    sortActivities(activities) {
+        if (this.state.sortDescending) {
+            return activities.sort((a, b) => a.timestamp - b.timestamp);
+        } else {
+            return activities.reverse();
+        }
+    }
 }
 
 export default ActivityLogView;
index bd40e11..0dbf518 100644 (file)
@@ -1,28 +1,36 @@
-import React, {Component} from 'react';
-// eslint-disable-next-line max-len
-const style = 'LnJhYmJpdHt3aWR0aDo1ZW07aGVpZ2h0OjNlbTtiYWNrZ3JvdW5kOiM5OTk7Ym9yZGVyLXJhZGl1czo3MCUgOTAlIDYwJSA1MCU7cG9zaXRpb246cmVsYXRpdmU7LW1vei10cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApOy1tcy10cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoLTJlbSwwKTt0cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApO2FuaW1hdGlvbjpob3AgMXMgaW5maW5pdGUgbGluZWFyO3otaW5kZXg6MX0ucmFiYml0OmFmdGVyLC5yYWJiaXQ6YmVmb3Jle2NvbnRlbnQ6IiI7cG9zaXRpb246YWJzb2x1dGU7YmFja2dyb3VuZDojZjFmMWYxfS5uby1mbGV4Ym94IC5yYWJiaXR7bWFyZ2luOjEwZW0gYXV0byAwfS5yYWJiaXQ6YmVmb3Jle3dpZHRoOjFlbTtoZWlnaHQ6MWVtO2JvcmRlci1yYWRpdXM6MTAwJTt0b3A6LjVlbTtsZWZ0Oi0uM2VtO2JveC1zaGFkb3c6NGVtIC40ZW0gMCAtLjM1ZW0gIzNmMzMzNCwuNWVtIDFlbSAwICNmMWYxZjEsNGVtIDFlbSAwIC0uM2VtICNmMWYxZjEsNGVtIDFlbSAwIC0uM2VtICNmMWYxZjEsNGVtIDFlbSAwIC0uNGVtICNmMWYxZjE7YW5pbWF0aW9uOmtpY2sgMXMgaW5maW5pdGUgbGluZWFyfS5yYWJiaXQ6YWZ0ZXJ7d2lkdGg6Ljc1ZW07aGVpZ2h0OjJlbTtib3JkZXItcmFkaXVzOjUwJSAxMDAlIDAgMDstbW96LXRyYW5zZm9ybTpyb3RhdGUoLTMwZGVnKTstbXMtdHJhbnNmb3JtOnJvdGF0ZSgtMzBkZWcpOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgtMzBkZWcpO3RyYW5zZm9ybTpyb3RhdGUoLTMwZGVnKTtyaWdodDoxZW07dG9wOi0xZW07Ym9yZGVyLXRvcDoxcHggc29saWQgI2Y3ZjVmNDtib3JkZXItbGVmdDoxcHggc29saWQgI2Y3ZjVmNDtib3gtc2hhZG93Oi0uNWVtIDAgMCAtLjFlbSAjZjFmMWYxfUBrZXlmcmFtZXMgaG9wezIwJXstbW96LXRyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pOy1tcy10cmFuc2Zvcm06cm90YXRlKC0xMGRlZykgdHJhbnNsYXRlKDFlbSwtMmVtKTstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pO3RyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pfTQwJXstbW96LXRyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSk7LW1zLXRyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSk7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKDEwZGVnKSB0cmFuc2xhdGUoM2VtLC00ZW0pO3RyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSl9NjAlLDc1JXstbW96LXRyYW5zZm9ybTpyb3RhdGUoMCkgdHJhbnNsYXRlKDRlbSwwKTstbXMtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoNGVtLDApOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoNGVtLDApO3RyYW5zZm9ybTpyb3RhdGUoMCkgdHJhbnNsYXRlKDRlbSwwKX19QGtleWZyYW1lcyBraWNrezIwJSw1MCV7Ym94LXNoYWRvdzo0ZW0gLjRlbSAwIC0uMzVlbSAjM2YzMzM0LC41ZW0gMS41ZW0gMCAjZjFmMWYxLDRlbSAxLjc1ZW0gMCAtLjNlbSAjZjFmMWYxLDRlbSAxLjc1ZW0gMCAtLjNlbSAjZjFmMWYxLDRlbSAxLjllbSAwIC0uNGVtICNmMWYxZjF9NDAle2JveC1zaGFkb3c6NGVtIC40ZW0gMCAtLjM1ZW0gIzNmMzMzNCwuNWVtIDJlbSAwICNmMWYxZjEsNGVtIDEuNzVlbSAwIC0uM2VtICNmMWYxZjEsNC4yZW0gMS43NWVtIDAgLS4yZW0gI2YxZjFmMSw0LjRlbSAxLjllbSAwIC0uMmVtICNmMWYxZjF9fQ==';
+import React, { Component } from 'react'; /* eslint-disable max-len */
+const style =
+    'LnJhYmJpdHt3aWR0aDo1ZW07aGVpZ2h0OjNlbTtiYWNrZ3JvdW5kOiM5OTk7Ym9yZGVyLXJhZGl1czo3MCUgOTAlIDYwJSA1MCU7cG9zaXRpb246cmVsYXRpdmU7LW1vei10cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApOy1tcy10cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoLTJlbSwwKTt0cmFuc2Zvcm06cm90YXRlKDApIHRyYW5zbGF0ZSgtMmVtLDApO2FuaW1hdGlvbjpob3AgMXMgaW5maW5pdGUgbGluZWFyO3otaW5kZXg6MX0ucmFiYml0OmFmdGVyLC5yYWJiaXQ6YmVmb3Jle2NvbnRlbnQ6IiI7cG9zaXRpb246YWJzb2x1dGU7YmFja2dyb3VuZDojZjFmMWYxfS5uby1mbGV4Ym94IC5yYWJiaXR7bWFyZ2luOjEwZW0gYXV0byAwfS5yYWJiaXQ6YmVmb3Jle3dpZHRoOjFlbTtoZWlnaHQ6MWVtO2JvcmRlci1yYWRpdXM6MTAwJTt0b3A6LjVlbTtsZWZ0Oi0uM2VtO2JveC1zaGFkb3c6NGVtIC40ZW0gMCAtLjM1ZW0gIzNmMzMzNCwuNWVtIDFlbSAwICNmMWYxZjEsNGVtIDFlbSAwIC0uM2VtICNmMWYxZjEsNGVtIDFlbSAwIC0uM2VtICNmMWYxZjEsNGVtIDFlbSAwIC0uNGVtICNmMWYxZjE7YW5pbWF0aW9uOmtpY2sgMXMgaW5maW5pdGUgbGluZWFyfS5yYWJiaXQ6YWZ0ZXJ7d2lkdGg6Ljc1ZW07aGVpZ2h0OjJlbTtib3JkZXItcmFkaXVzOjUwJSAxMDAlIDAgMDstbW96LXRyYW5zZm9ybTpyb3RhdGUoLTMwZGVnKTstbXMtdHJhbnNmb3JtOnJvdGF0ZSgtMzBkZWcpOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgtMzBkZWcpO3RyYW5zZm9ybTpyb3RhdGUoLTMwZGVnKTtyaWdodDoxZW07dG9wOi0xZW07Ym9yZGVyLXRvcDoxcHggc29saWQgI2Y3ZjVmNDtib3JkZXItbGVmdDoxcHggc29saWQgI2Y3ZjVmNDtib3gtc2hhZG93Oi0uNWVtIDAgMCAtLjFlbSAjZjFmMWYxfUBrZXlmcmFtZXMgaG9wezIwJXstbW96LXRyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pOy1tcy10cmFuc2Zvcm06cm90YXRlKC0xMGRlZykgdHJhbnNsYXRlKDFlbSwtMmVtKTstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pO3RyYW5zZm9ybTpyb3RhdGUoLTEwZGVnKSB0cmFuc2xhdGUoMWVtLC0yZW0pfTQwJXstbW96LXRyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSk7LW1zLXRyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSk7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKDEwZGVnKSB0cmFuc2xhdGUoM2VtLC00ZW0pO3RyYW5zZm9ybTpyb3RhdGUoMTBkZWcpIHRyYW5zbGF0ZSgzZW0sLTRlbSl9NjAlLDc1JXstbW96LXRyYW5zZm9ybTpyb3RhdGUoMCkgdHJhbnNsYXRlKDRlbSwwKTstbXMtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoNGVtLDApOy13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgwKSB0cmFuc2xhdGUoNGVtLDApO3RyYW5zZm9ybTpyb3RhdGUoMCkgdHJhbnNsYXRlKDRlbSwwKX19QGtleWZyYW1lcyBraWNrezIwJSw1MCV7Ym94LXNoYWRvdzo0ZW0gLjRlbSAwIC0uMzVlbSAjM2YzMzM0LC41ZW0gMS41ZW0gMCAjZjFmMWYxLDRlbSAxLjc1ZW0gMCAtLjNlbSAjZjFmMWYxLDRlbSAxLjc1ZW0gMCAtLjNlbSAjZjFmMWYxLDRlbSAxLjllbSAwIC0uNGVtICNmMWYxZjF9NDAle2JveC1zaGFkb3c6NGVtIC40ZW0gMCAtLjM1ZW0gIzNmMzMzNCwuNWVtIDJlbSAwICNmMWYxZjEsNGVtIDEuNzVlbSAwIC0uM2VtICNmMWYxZjEsNC4yZW0gMS43NWVtIDAgLS4yZW0gI2YxZjFmMSw0LjRlbSAxLjllbSAwIC0uMmVtICNmMWYxZjF9fQ==';
+/* eslint-enable max-len */
 class LogixUtil extends Component {
+    state = {
+        whatToDisplay: false
+    };
 
-       state = {
-               whatToDisplay: false
-       };
-
-       componentWillReceiveProps(nextProps) {
-               this.setState({whatToDisplay: window.btoa(nextProps.display) === 'YnJpdG5leSBiaXRjaCE='});
-       }
-
-       render() {
-               if (this.state.whatToDisplay) {
-                       setTimeout(() => this.setState({whatToDisplay: false}), 5000);
-               }
-               return (
-                       <div style={{display: this.state.whatToDisplay ? 'block' : 'none', position: 'fixed',top: '50%', left: '45%'}}>
-                               <style>{window.atob(style)}</style>
-                               <div className='rabbit'></div>
-                       </div>
-               );
-       }
+    componentWillReceiveProps(nextProps) {
+        this.setState({
+            whatToDisplay:
+                window.btoa(nextProps.display) === 'YnJpdG5leSBiaXRjaCE='
+        });
+    }
 
+    render() {
+        if (this.state.whatToDisplay) {
+            setTimeout(() => this.setState({ whatToDisplay: false }), 5000);
+        }
+        return (
+            <div
+                style={{
+                    display: this.state.whatToDisplay ? 'block' : 'none',
+                    position: 'fixed',
+                    top: '50%',
+                    left: '45%'
+                }}>
+                <style>{window.atob(style)}</style>
+                <div className="rabbit" />
+            </div>
+        );
+    }
 }
 
 export default LogixUtil;
index 05affe9..99ecae9 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {permissionTypes} from 'sdc-app/onboarding/permissions/PermissionsConstants.js';
-import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
-import {actionTypes as onboardingActionTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { permissionTypes } from 'sdc-app/onboarding/permissions/PermissionsConstants.js';
+import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import { actionTypes as onboardingActionTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import restToggle from 'sdc-app/features/restToggle.js';
-import {featureToggleNames} from 'sdc-app/features/FeaturesConstants.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 export const archiveActions = {
-       ARCHIVE: 'ARCHIVE',
-       RESTORE: 'RESTORE'
+    ARCHIVE: 'ARCHIVE',
+    RESTORE: 'RESTORE'
 };
 
 export const itemStatus = {
-       ARCHIVED: 'ARCHIVED',
-       DRAFT: 'Draft',
-       CERTIFIED: 'Certified'
+    ARCHIVED: 'ARCHIVED',
+    DRAFT: 'Draft',
+    CERTIFIED: 'Certified'
 };
 
-
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/items`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/items`;
 }
 
 const ItemsHelper = {
-       performVCAction({itemId, version, action, comment}) {
-               const {id: versionId} = version;
-               const data = {
-                       action,
-                       ...action === VersionControllerActionsEnum.COMMIT && {commitRequest: {message: comment}}
-               };
-               return RestAPIUtil.put(`${baseUrl()}/${itemId}/versions/${versionId}/actions`, data);
-       },
+    performVCAction({ itemId, version, action, comment }) {
+        const { id: versionId } = version;
+        const data = {
+            action,
+            ...(action === VersionControllerActionsEnum.COMMIT && {
+                commitRequest: { message: comment }
+            })
+        };
+        return RestAPIUtil.put(
+            `${baseUrl()}/${itemId}/versions/${versionId}/actions`,
+            data
+        );
+    },
 
-       fetchVersions({itemId}) {
-               return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/versions`);
-       },
+    fetchVersions({ itemId }) {
+        return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/versions`);
+    },
 
-       fetchVersion({itemId, versionId}) {
-               return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/versions/${versionId}`);
-       },
+    fetchVersion({ itemId, versionId }) {
+        return RestAPIUtil.fetch(
+            `${baseUrl()}/${itemId}/versions/${versionId}`
+        );
+    },
 
-       fetchActivityLog({itemId, versionId}) {
-               return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/versions/${versionId}/activity-logs`);
-       },
+    fetchActivityLog({ itemId, versionId }) {
+        return RestAPIUtil.fetch(
+            `${baseUrl()}/${itemId}/versions/${versionId}/activity-logs`
+        );
+    },
 
-       fetchUsers({itemId}) {
-               return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/permissions`);
-       },
+    fetchUsers({ itemId }) {
+        return RestAPIUtil.fetch(`${baseUrl()}/${itemId}/permissions`);
+    },
 
-       updateContributors({itemId, removedUsersIds, addedUsersIds}) {
-               return RestAPIUtil.put(`${baseUrl()}/${itemId}/permissions/${permissionTypes.CONTRIBUTOR}`, {removedUsersIds, addedUsersIds});
-       },
+    updateContributors({ itemId, removedUsersIds, addedUsersIds }) {
+        return RestAPIUtil.put(
+            `${baseUrl()}/${itemId}/permissions/${permissionTypes.CONTRIBUTOR}`,
+            { removedUsersIds, addedUsersIds }
+        );
+    },
 
-       changeOwner({itemId, ownerId}) {
-               return RestAPIUtil.put(`${baseUrl()}/${itemId}/permissions/${permissionTypes.OWNER}`, {removedUsersIds: [], addedUsersIds: [ownerId]});
-       },
+    changeOwner({ itemId, ownerId }) {
+        return RestAPIUtil.put(
+            `${baseUrl()}/${itemId}/permissions/${permissionTypes.OWNER}`,
+            { removedUsersIds: [], addedUsersIds: [ownerId] }
+        );
+    },
 
-       async checkItemStatus(dispatch, {itemId, versionId}) {
-               const response = await ItemsHelper.fetchVersion({itemId, versionId});
-               let state = response && response.state || {};
-               const {baseId, description, id, name, status} = response;
-               const item = await ItemsHelper.fetchItem(itemId);
-               dispatch({
-                       type: onboardingActionTypes.UPDATE_ITEM_STATUS,
-                       itemState: state,
-                       itemStatus: response.status,
-                       archivedStatus: item.status,
-                       updatedVersion: {baseId, description, id, name, status}
-               });
+    async checkItemStatus(dispatch, { itemId, versionId }) {
+        const response = await ItemsHelper.fetchVersion({ itemId, versionId });
+        let state = (response && response.state) || {};
+        const { baseId, description, id, name, status } = response;
+        const item = await ItemsHelper.fetchItem(itemId);
+        dispatch({
+            type: onboardingActionTypes.UPDATE_ITEM_STATUS,
+            itemState: state,
+            itemStatus: response.status,
+            archivedStatus: item.status,
+            updatedVersion: { baseId, description, id, name, status }
+        });
 
-               return Promise.resolve({...response, archivedStatus: item.status});
-       },
+        return Promise.resolve({ ...response, archivedStatus: item.status });
+    },
 
-       fetchItem(itemId) {
-               return restToggle({restFunction: () => RestAPIUtil.fetch(`${baseUrl()}/${itemId}`), featureName: featureToggleNames.ARCHIVE_ITEM, mockResult: {}});
-       },
+    fetchItem(itemId) {
+        return restToggle({
+            restFunction: () => RestAPIUtil.fetch(`${baseUrl()}/${itemId}`),
+            featureName: featureToggleNames.ARCHIVE_ITEM,
+            mockResult: {}
+        });
+    },
 
-       archiveItem(itemId) {
-               return RestAPIUtil.put(`${baseUrl()}/${itemId}/actions`, {
-                       action: archiveActions.ARCHIVE
-               });
-       },
-       restoreItem(itemId) {
-               return RestAPIUtil.put(`${baseUrl()}/${itemId}/actions`, {
-                       action: archiveActions.RESTORE
-               });
-       }
+    archiveItem(itemId) {
+        return RestAPIUtil.put(`${baseUrl()}/${itemId}/actions`, {
+            action: archiveActions.ARCHIVE
+        });
+    },
+    restoreItem(itemId) {
+        return RestAPIUtil.put(`${baseUrl()}/${itemId}/actions`, {
+            action: archiveActions.RESTORE
+        });
+    }
 };
 
 export default ItemsHelper;
index 7c05f84..6f69cd0 100644 (file)
-import {itemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
-import {actionTypes as SoftwareProductActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { actionTypes as SoftwareProductActionTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 const ScreensHelper = {
-       async loadScreen(dispatch, {screen, screenType, props}) {
-               if(screen === enums.SCREEN.ONBOARDING_CATALOG) {
-                       OnboardingActionHelper.navigateToOnboardingCatalog(dispatch);
-                       return;
-               }
-               
-               screenType = !screenType ? this.getScreenType(screen) : screenType;
+    async loadScreen(dispatch, { screen, screenType, props }) {
+        if (screen === enums.SCREEN.ONBOARDING_CATALOG) {
+            OnboardingActionHelper.navigateToOnboardingCatalog(dispatch);
+            return;
+        }
 
-               if(screenType === screenTypes.LICENSE_MODEL) {
-                       const {licenseModelId, version, licenseModel, usersList} = props;
-                       const item = await ItemsHelper.fetchItem(licenseModelId);
-                       let itemStatusPromise = version && screen ?
-                               ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id}) :
-                               Promise.resolve();
-                       itemStatusPromise.then((updatedVersion) => {
-                               if (updatedVersion && updatedVersion.status !== version.status) {
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                                               data: {
-                                                       title: i18n('Commit error'),
-                                                       msg: i18n('Item version was certified by Owner'),
-                                                       cancelButtonText: i18n('Cancel')
-                                               }
-                                       });
-                                       versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: licenseModelId});
-                               }
-                               let newVersion = updatedVersion ? updatedVersion : version;
-                               const screenProps = {licenseModelId, version: newVersion, status: item.status};
-                               switch (screen) {
-                                       case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
-                                               OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.LICENSE_AGREEMENTS:
-                                               OnboardingActionHelper.navigateToLicenseAgreements(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.FEATURE_GROUPS:
-                                               OnboardingActionHelper.navigateToFeatureGroups(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.ENTITLEMENT_POOLS:
-                                               OnboardingActionHelper.navigateToEntitlementPools(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.LICENSE_KEY_GROUPS:
-                                               OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.ACTIVITY_LOG:
-                                               OnboardingActionHelper.navigateToLicenseModelActivityLog(dispatch, screenProps);
-                                               break;
-                                       case enums.SCREEN.VERSIONS_PAGE:
-                                       default:
-                                               OnboardingActionHelper.navigateToVersionsPage(dispatch, {
-                                                       itemId: licenseModelId,
-                                                       itemType: itemTypes.LICENSE_MODEL,
-                                                       itemName: licenseModel.name,
-                                                       users: usersList
-                                               });
-                                               break;
-                               }
-                       });
-               }
+        screenType = !screenType ? this.getScreenType(screen) : screenType;
 
-               else if(screenType === screenTypes.SOFTWARE_PRODUCT) {
-                       const {softwareProductId, componentId, version, softwareProduct, usersList} = props;
-                       const item = await ItemsHelper.fetchItem(softwareProductId);
-                       let itemStatusPromise = version && screen ?
-                               ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id}) :
-                               Promise.resolve();
-                       itemStatusPromise.then((updatedVersion) => {
-                               if (updatedVersion && updatedVersion.status !== version.status) {
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                                               data: {
-                                                       title: i18n('Commit error'),
-                                                       msg: i18n('Item version already Certified'),
-                                                       cancelButtonText: i18n('Cancel')
-                                               }
-                                       });
-                                       versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId});
-                               }
+        if (screenType === screenTypes.LICENSE_MODEL) {
+            const { licenseModelId, version, licenseModel, usersList } = props;
+            const item = await ItemsHelper.fetchItem(licenseModelId);
+            let itemStatusPromise =
+                version && screen
+                    ? ItemsHelper.checkItemStatus(dispatch, {
+                          itemId: licenseModelId,
+                          versionId: version.id
+                      })
+                    : Promise.resolve();
+            itemStatusPromise.then(updatedVersion => {
+                if (
+                    updatedVersion &&
+                    updatedVersion.status !== version.status
+                ) {
+                    dispatch({
+                        type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                        data: {
+                            title: i18n('Commit error'),
+                            msg: i18n('Item version was certified by Owner'),
+                            cancelButtonText: i18n('Cancel')
+                        }
+                    });
+                    versionPageActionHelper.fetchVersions(dispatch, {
+                        itemType: itemTypes.LICENSE_MODEL,
+                        itemId: licenseModelId
+                    });
+                }
+                let newVersion = updatedVersion ? updatedVersion : version;
+                const screenProps = {
+                    licenseModelId,
+                    version: newVersion,
+                    status: item.status
+                };
+                switch (screen) {
+                    case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+                        OnboardingActionHelper.navigateToLicenseModelOverview(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.LICENSE_AGREEMENTS:
+                        OnboardingActionHelper.navigateToLicenseAgreements(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.FEATURE_GROUPS:
+                        OnboardingActionHelper.navigateToFeatureGroups(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.ENTITLEMENT_POOLS:
+                        OnboardingActionHelper.navigateToEntitlementPools(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.LICENSE_KEY_GROUPS:
+                        OnboardingActionHelper.navigateToLicenseKeyGroups(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.ACTIVITY_LOG:
+                        OnboardingActionHelper.navigateToLicenseModelActivityLog(
+                            dispatch,
+                            screenProps
+                        );
+                        break;
+                    case enums.SCREEN.VERSIONS_PAGE:
+                    default:
+                        OnboardingActionHelper.navigateToVersionsPage(
+                            dispatch,
+                            {
+                                itemId: licenseModelId,
+                                itemType: itemTypes.LICENSE_MODEL,
+                                itemName: licenseModel.name,
+                                users: usersList
+                            }
+                        );
+                        break;
+                }
+            });
+        } else if (screenType === screenTypes.SOFTWARE_PRODUCT) {
+            const {
+                softwareProductId,
+                componentId,
+                version,
+                softwareProduct,
+                usersList
+            } = props;
+            const item = await ItemsHelper.fetchItem(softwareProductId);
+            let itemStatusPromise =
+                version && screen
+                    ? ItemsHelper.checkItemStatus(dispatch, {
+                          itemId: softwareProductId,
+                          versionId: version.id
+                      })
+                    : Promise.resolve();
+            itemStatusPromise.then(updatedVersion => {
+                if (
+                    updatedVersion &&
+                    updatedVersion.status !== version.status
+                ) {
+                    dispatch({
+                        type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                        data: {
+                            title: i18n('Commit error'),
+                            msg: i18n('Item version already Certified'),
+                            cancelButtonText: i18n('Cancel')
+                        }
+                    });
+                    versionPageActionHelper.fetchVersions(dispatch, {
+                        itemType: itemTypes.SOFTWARE_PRODUCT,
+                        itemId: softwareProductId
+                    });
+                }
 
-                               let newVersion = updatedVersion ? updatedVersion : version;
-                               
-                               const props = {
-                                       softwareProductId,
-                                       componentId,
-                                       version: newVersion,
-                                       status: item.status
-                               };
-                               if (screen === screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL) {
-                                       OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, props);
-                               }
-                               
-                               switch (screen) {
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-                                               OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                                               OnboardingActionHelper.navigateToSoftwareProductComponentGeneral(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                                               OnboardingActionHelper.navigateToComponentCompute(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                                               OnboardingActionHelper.navigateToComponentLoadBalancing(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                                               OnboardingActionHelper.navigateToComponentNetwork(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                                               OnboardingActionHelper.navigateToComponentStorage(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-                                               OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                                               OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                                               OnboardingActionHelper.navigateToComponentImages(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-                                               OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                                               OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP:
-                                               OnboardingActionHelper.navigateToSoftwareProductAttachmentsSetupTab(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION:
-                                               OnboardingActionHelper.navigateToSoftwareProductAttachmentsValidationTab(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-                                               OnboardingActionHelper.navigateToSoftwareProductProcesses(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-                                               OnboardingActionHelper.navigateToSoftwareProductDeployment(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-                                               OnboardingActionHelper.navigateToSoftwareProductNetworks(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-                                               OnboardingActionHelper.navigateToSoftwareProductDependencies(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-                                               OnboardingActionHelper.navigateToSoftwareProductActivityLog(dispatch, props);
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-                                               OnboardingActionHelper.navigateToSoftwareProductComponents(dispatch, props);
-                                               dispatch({
-                                                       type: SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
-                                                       mapOfExpandedIds: {
-                                                               [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: true
-                                                       }
-                                               });
-                                               break;
-                                       case enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE:
-                                       default:
-                                               OnboardingActionHelper.navigateToVersionsPage(dispatch, {
-                                                       itemId: softwareProductId,
-                                                       itemType: itemTypes.SOFTWARE_PRODUCT,
-                                                       itemName: softwareProduct.name,
-                                                       users: usersList,
-                                                       additionalProps: {
-                                                               licenseModelId: softwareProduct.vendorId,
-                                                               licensingVersion: softwareProduct.licensingVersion
-                                                       }
-                                               });
-                                               break;  
-                               }
-                       });
-               }
-       },
+                let newVersion = updatedVersion ? updatedVersion : version;
 
-       getScreenType(screen) {
-               switch (screen) {
-                       case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
-                       case enums.SCREEN.LICENSE_AGREEMENTS:
-                       case enums.SCREEN.FEATURE_GROUPS:
-                       case enums.SCREEN.ENTITLEMENT_POOLS:
-                       case enums.SCREEN.LICENSE_KEY_GROUPS:
-                       case enums.SCREEN.ACTIVITY_LOG:
-                               return screenTypes.LICENSE_MODEL;
-                       case screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-                               return screenTypes.SOFTWARE_PRODUCT;
-               }
-       },
+                const props = {
+                    softwareProductId,
+                    componentId,
+                    version: newVersion,
+                    status: item.status
+                };
+                if (
+                    screen ===
+                    screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL
+                ) {
+                    OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(
+                        dispatch,
+                        props
+                    );
+                }
 
-       loadLandingScreen(dispatch, {previousScreenName, screenType, props: {licenseModelId, softwareProductId, version}}) {
-               let selectedScreenType = screenType ? screenType : this.getScreenType(previousScreenName);
-               let screen = selectedScreenType === screenTypes.SOFTWARE_PRODUCT ?
-                       enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE :
-                       enums.SCREEN.LICENSE_MODEL_OVERVIEW;
-               let props = {licenseModelId, softwareProductId, version};
-               return this.loadScreen(dispatch, {screen, screenType: selectedScreenType, props});
-       }
+                switch (screen) {
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+                        OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+                        OnboardingActionHelper.navigateToSoftwareProductComponentGeneral(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+                        OnboardingActionHelper.navigateToComponentCompute(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+                        OnboardingActionHelper.navigateToComponentLoadBalancing(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+                        OnboardingActionHelper.navigateToComponentNetwork(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+                        OnboardingActionHelper.navigateToComponentStorage(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+                        OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+                        OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+                        OnboardingActionHelper.navigateToComponentImages(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
+                        OnboardingActionHelper.navigateToSoftwareProductLandingPage(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
+                        OnboardingActionHelper.navigateToSoftwareProductDetails(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP:
+                        OnboardingActionHelper.navigateToSoftwareProductAttachmentsSetupTab(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION:
+                        OnboardingActionHelper.navigateToSoftwareProductAttachmentsValidationTab(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
+                        OnboardingActionHelper.navigateToSoftwareProductProcesses(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
+                        OnboardingActionHelper.navigateToSoftwareProductDeployment(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
+                        OnboardingActionHelper.navigateToSoftwareProductNetworks(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+                        OnboardingActionHelper.navigateToSoftwareProductDependencies(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+                        OnboardingActionHelper.navigateToSoftwareProductActivityLog(
+                            dispatch,
+                            props
+                        );
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+                        OnboardingActionHelper.navigateToSoftwareProductComponents(
+                            dispatch,
+                            props
+                        );
+                        dispatch({
+                            type:
+                                SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
+                            mapOfExpandedIds: {
+                                [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: true
+                            }
+                        });
+                        break;
+                    case enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE:
+                    default:
+                        OnboardingActionHelper.navigateToVersionsPage(
+                            dispatch,
+                            {
+                                itemId: softwareProductId,
+                                itemType: itemTypes.SOFTWARE_PRODUCT,
+                                itemName: softwareProduct.name,
+                                users: usersList,
+                                additionalProps: {
+                                    licenseModelId: softwareProduct.vendorId,
+                                    licensingVersion:
+                                        softwareProduct.licensingVersion
+                                }
+                            }
+                        );
+                        break;
+                }
+            });
+        }
+    },
+
+    getScreenType(screen) {
+        switch (screen) {
+            case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+            case enums.SCREEN.LICENSE_AGREEMENTS:
+            case enums.SCREEN.FEATURE_GROUPS:
+            case enums.SCREEN.ENTITLEMENT_POOLS:
+            case enums.SCREEN.LICENSE_KEY_GROUPS:
+            case enums.SCREEN.ACTIVITY_LOG:
+                return screenTypes.LICENSE_MODEL;
+            case screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
+            case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+                return screenTypes.SOFTWARE_PRODUCT;
+        }
+    },
+
+    loadLandingScreen(
+        dispatch,
+        {
+            previousScreenName,
+            screenType,
+            props: { licenseModelId, softwareProductId, version }
+        }
+    ) {
+        let selectedScreenType = screenType
+            ? screenType
+            : this.getScreenType(previousScreenName);
+        let screen =
+            selectedScreenType === screenTypes.SOFTWARE_PRODUCT
+                ? enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE
+                : enums.SCREEN.LICENSE_MODEL_OVERVIEW;
+        let props = { licenseModelId, softwareProductId, version };
+        return this.loadScreen(dispatch, {
+            screen,
+            screenType: selectedScreenType,
+            props
+        });
+    }
 };
 
 export default ScreensHelper;
index cfa6752..aa578c6 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes as commonActionTypes} from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
-import {actionTypes as qcommonActionTypes} from 'sdc-app/common/reducers/JSONSchemaReducerConstants.js';
+import { actionTypes as commonActionTypes } from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
+import { actionTypes as qcommonActionTypes } from 'sdc-app/common/reducers/JSONSchemaReducerConstants.js';
 
 class ValidationHelper {
+    static dataChanged(
+        dispatch,
+        { deltaData, formName, customValidations = {} }
+    ) {
+        dispatch({
+            type: commonActionTypes.DATA_CHANGED,
+            deltaData,
+            formName,
+            customValidations
+        });
+    }
 
-       static dataChanged(dispatch, {deltaData, formName, customValidations = {}}){
-               dispatch({
-                       type: commonActionTypes.DATA_CHANGED,
-                       deltaData,
-                       formName,
-                       customValidations
-               });
-       }
+    static validateForm(dispatch, formName) {
+        dispatch({
+            type: commonActionTypes.VALIDATE_FORM,
+            formName
+        });
+    }
 
-       static validateForm(dispatch, formName){
-               dispatch({
-                       type: commonActionTypes.VALIDATE_FORM,
-                       formName
-               });
-       }
+    static validateData(dispatch, { formName, data }) {
+        dispatch({
+            type: commonActionTypes.VALIDATE_DATA,
+            formName,
+            data
+        });
+    }
 
-       static validateData(dispatch, {formName, data}) {
-               dispatch({
-                       type: commonActionTypes.VALIDATE_DATA,
-                       formName,
-                       data
-               });
-       }
+    static qValidateData(dispatch, { data, qName, customValidations = {} }) {
+        dispatch({
+            type: qcommonActionTypes.VALIDATE_DATA,
+            data,
+            qName,
+            customValidations
+        });
+    }
 
-       static qValidateData(dispatch, {data, qName, customValidations = {}}) {
-               dispatch({
-                       type: qcommonActionTypes.VALIDATE_DATA,
-                       data,
-                       qName,
-                       customValidations
-               });
-       }
+    static qValidateForm(dispatch, qName, customValidations) {
+        dispatch({
+            type: qcommonActionTypes.VALIDATE_FORM,
+            qName,
+            customValidations
+        });
+    }
 
-       static qValidateForm(dispatch, qName, customValidations){
-               dispatch({
-                       type: qcommonActionTypes.VALIDATE_FORM,
-                       qName,
-                       customValidations
-               });
-       }
+    static qDataChanged(
+        dispatch,
+        { deltaData, qName, customValidations = {} }
+    ) {
+        dispatch({
+            type: qcommonActionTypes.DATA_CHANGED,
+            deltaData,
+            qName,
+            customValidations
+        });
+    }
 
-       static qDataChanged(dispatch, {deltaData, qName, customValidations = {}}){
-               dispatch({
-                       type: qcommonActionTypes.DATA_CHANGED,
-                       deltaData,
-                       qName,
-                       customValidations
-               });
-       }
+    static qDataLoaded(dispatch, { qName, response: { qdata, qschema } }) {
+        dispatch({
+            type: qcommonActionTypes.DATA_LOADED,
+            payload: {
+                qdata,
+                qschema
+            },
+            qName
+        });
+    }
 
-       static qDataLoaded(dispatch, {qName, response: {qdata, qschema}}) {
-               dispatch({
-                       type: qcommonActionTypes.DATA_LOADED,
-                       payload: {
-                               qdata,
-                               qschema
-                       },
-                       qName
-               });
-       }
-
-       static checkFormValid(genericFieldInfo) {
-               for (let field in genericFieldInfo) {
-                       if (!genericFieldInfo[field].isValid) {
-                               return false;
-                       }
-               }
-               return true;
-       }
+    static checkFormValid(genericFieldInfo) {
+        for (let field in genericFieldInfo) {
+            if (!genericFieldInfo[field].isValid) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
 
 export default ValidationHelper;
index baf00cf..81f7174 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import MergeEditorView from './MergeEditorView.jsx';
 import MergeEditorActionHelper from './MergeEditorActionHelper.js';
 
-export const mapStateToProps = ({mergeEditor, currentScreen}) => {
-       let {props} = currentScreen;
-       let item = {
-               id: props.softwareProductId || props.licenseModelId,
-               version: props.version
-       };
-       return {...mergeEditor, item, currentScreen};
+export const mapStateToProps = ({ mergeEditor, currentScreen }) => {
+    let { props } = currentScreen;
+    let item = {
+        id: props.softwareProductId || props.licenseModelId,
+        version: props.version
+    };
+    return { ...mergeEditor, item, currentScreen };
 };
 
-export const mapActionsToProps = (dispatch) => {
-       return {
-               fetchConflict: ({cid, itemId, version}) => MergeEditorActionHelper.fetchConflict(dispatch, {itemId, version, cid}),
-               onResolveConflict: ({conflictId, resolution, itemId, version, currentScreen}) =>
-                       MergeEditorActionHelper.resolveConflict(dispatch, {itemId, version, conflictId, resolution, currentScreen})
-       };
+export const mapActionsToProps = dispatch => {
+    return {
+        fetchConflict: ({ cid, itemId, version }) =>
+            MergeEditorActionHelper.fetchConflict(dispatch, {
+                itemId,
+                version,
+                cid
+            }),
+        onResolveConflict: ({
+            conflictId,
+            resolution,
+            itemId,
+            version,
+            currentScreen
+        }) =>
+            MergeEditorActionHelper.resolveConflict(dispatch, {
+                itemId,
+                version,
+                conflictId,
+                resolution,
+                currentScreen
+            })
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(MergeEditorView);
index 92ec60b..c54b9fe 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, rules, dataRules, SyncStates} from './MergeEditorConstants.js';
+import {
+    actionTypes,
+    rules,
+    dataRules,
+    SyncStates
+} from './MergeEditorConstants.js';
 import cloneDeep from 'lodash/cloneDeep.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import ItemsHelper from '../../common/helpers/ItemsHelper.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.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 {optionsInputValues as epOptionsValues} from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
-import {optionsInputValues as laOptionsValues} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
-import {optionsInputValues as processOptionValues} from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
-import {selectValues as limitSelectValues} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import { optionsInputValues as epOptionsValues } from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
+import { optionsInputValues as laOptionsValues } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
+import { optionsInputValues as processOptionValues } from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
+import { selectValues as limitSelectValues } from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
 import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
 import moment from 'moment';
-import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 
 function softwareProductCategoriesUrl() {
-       const restCatalogPrefix = Configuration.get('restCatalogPrefix');
-       return `${restCatalogPrefix}/v1/categories/resources/`;
+    const restCatalogPrefix = Configuration.get('restCatalogPrefix');
+    return `${restCatalogPrefix}/v1/categories/resources/`;
 }
 
 function versionUrl(itemId, versionId) {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
 }
 
 function baseUrl(itemId, version, conflictId) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
-       return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
+    return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
 }
 
-function fetchConflicts({itemId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
+function fetchConflicts({ itemId, version }) {
+    return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
 }
 
-function fetchConflictById({itemId, version, cid}) {
-       return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
+function fetchConflictById({ itemId, version, cid }) {
+    return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
 }
 
-function resolveConflict({itemId, version, conflictId, resolution}) {
-       return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {resolution});
+function resolveConflict({ itemId, version, conflictId, resolution }) {
+    return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {
+        resolution
+    });
 }
 
 function fetchCategories() {
-       return RestAPIUtil.fetch(softwareProductCategoriesUrl());
+    return RestAPIUtil.fetch(softwareProductCategoriesUrl());
 }
 
-function fetchVersion({vendorId, licensingVersion}) {
-       return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
+function fetchVersion({ vendorId, licensingVersion }) {
+    return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
 }
 
-function createCategoryStr(data, {categories}) {
-
-       let {category, subCategory} = data;
-       let foundCat = categories.find(element => element.uniqueId === category);
-       if (!foundCat) { return ''; }
-
-       let catName = foundCat.name;
-       let foundSub =  foundCat.subcategories.find(element => element.uniqueId === subCategory);
-       if (!foundSub) { return `${catName}`; }
-
-       let subcatName = foundSub.name;
-       return `${catName} - ${subcatName}`;
-
+function createCategoryStr(data, { categories }) {
+    let { category, subCategory } = data;
+    let foundCat = categories.find(element => element.uniqueId === category);
+    if (!foundCat) {
+        return '';
+    }
+
+    let catName = foundCat.name;
+    let foundSub = foundCat.subcategories.find(
+        element => element.uniqueId === subCategory
+    );
+    if (!foundSub) {
+        return `${catName}`;
+    }
+
+    let subcatName = foundSub.name;
+    return `${catName} - ${subcatName}`;
 }
 
-function getEnumValues({enums, list}) {
-
-       if (!list) { return ''; }
-       return list.map(item => enums.find(el => el.enum === item).title);
-
+function getEnumValues({ enums, list }) {
+    if (!list) {
+        return '';
+    }
+    return list.map(item => enums.find(el => el.enum === item).title);
 }
 
 const MergeEditorActionHelper = {
-
-       analyzeSyncResult(dispatch, {itemId, version}) {
-               return ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id}).then((response) => {
-                       let inMerge = response && response.state && response.state.synchronizationState === SyncStates.MERGE;
-                       if (inMerge) {
-                               MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(() =>
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                                               data: {
-                                                       modalComponentName: modalContentMapper.MERGE_EDITOR,
-                                                       modalClassName: 'merge-editor-modal',
-                                                       title: `${i18n('Merge Required')} - ${version.description}`,
-                                                       onDeclined: () => {
-                                                               dispatch({
-                                                                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-                                                               });
-                                                       },
-                                                       modalComponentProps: {
-                                                               size: 'lg',
-                                                               type: 'default'
-                                                       }
-                                               }
-                                       })
-                               );
-                       }
-                       return Promise.resolve({updatedVersion: response, inMerge, isDirty: response.state.dirty});
-               });
-       },
-
-       fetchConflicts(dispatch, {itemId, version}) {
-               return fetchConflicts({itemId, version}).then(
-                       (data) => {
-                               dispatch({
-                                       type: actionTypes.LOAD_CONFLICTS,
-                                       data
-                               });
-                               return data;
-                       }
-               );
-       },
-
-       fetchConflict(dispatch, {itemId, version, cid}) {
-               fetchConflictById({itemId, version, cid}).then(
-                       (data) => {
-                               let newData = {};
-                               newData = MergeEditorActionHelper.processConflict(dispatch, {conflict: data, itemId, cid, version});
-                               dispatch({
-                                       type: actionTypes.LOAD_CONFLICT,
-                                       data: newData
-                               });
-                       }
-               );
-       },
-
-       resolveConflict(dispatch, {itemId, version, conflictId, resolution, currentScreen}) {
-               resolveConflict({itemId, version, conflictId, resolution}).then(() => {
-                       MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(conflicts => {
-                               if(conflicts.conflictInfoList && conflicts.conflictInfoList.length === 0) {
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_CLOSE
-                                       });
-                                       ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: currentScreen.screen, props: currentScreen.props});
-                                       ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id});
-                               }
-                       });
-               });
-       },
-
-       createConflictObject(data, {cid, conflict, dispatch, itemId, version, isYours}) {
-
-               let newData = {};
-
-               for (let key in data) {
-
-                       if (data.hasOwnProperty(key)) {
-                               let value = data[key];
-                               let fieldRule = dataRules[conflict.type] && dataRules[conflict.type][key] || dataRules.general[key];
-
-                               if (fieldRule) {
-                                       switch (fieldRule.rule) {
-
-                                               case rules.SKIP:
-                                                       break;
-
-                                               case rules.BOOLEAN:
-                                                       let {trueValue, falseValue} = fieldRule;
-                                                       newData[key] = value === trueValue ? true : value === falseValue ? false : undefined;
-                                                       break;
-
-                                               case rules.PARSE:
-                                                       let {moveFields, subFields} = fieldRule;
-                                                       if (moveFields) {
-                                                               let fields = subFields || Object.keys(value);
-                                                               fields.forEach(field => {
-                                                                       newData[field] = MergeEditorActionHelper.createConflictObject(
-                                                                               value[field], {cid, conflict, dispatch, itemId, version, isYours}
-                                                                       );
-                                                               });
-                                                       } else {
-                                                               newData[key] = MergeEditorActionHelper.createConflictObject(
-                                                                       value, {cid, conflict, dispatch, itemId, version, isYours}
-                                                               );
-                                                       }
-                                                       break;
-
-                                               case rules.FUNCTION:
-                                                       let {args, functionName} = fieldRule;
-                                                       newData[key] = MergeEditorActionHelper[functionName](data, {
-                                                               cid, conflict, dispatch, version, fieldName: key, isYours, itemId, args
-                                                       });
-                                                       break;
-
-                                               default:
-                                                       newData[key] = value;
-                                                       break;
-                                       }
-
-                               } else {
-                                       newData[key] = value;
-
-                               }
-                       }
-               }
-
-               return newData;
-
-       },
-
-       getNamesFromIDs(data, {version, cid, dispatch, itemId, fieldName, isYours, args}) {
-
-               let idList = data[fieldName] || [];
-               let {fetchFunction, fetchField} = args;
-
-               let promises = idList.map(id =>
-                       new Promise(resolve =>
-                               MergeEditorActionHelper[fetchFunction](
-                                       dispatch, {licenseModelId: itemId, [fetchField]: id, version}
-                               ).then(item => resolve(item.name))
-                       )
-               );
-
-               Promise.all(promises).then(fetchedItems => {
-                       let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
-                       dispatch({
-                               type: actionTypes.DATA_PROCESSED,
-                               data: {
-                                       cid,
-                                       [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
-                               }
-                       });
-               });
-
-               return idList;
-
-       },
-
-       getFeatureGroups(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
-
-               let featureGroups = data[fieldName] || [];
-               if (!(featureGroups instanceof Array)) {
-                       featureGroups = [featureGroups];
-               }
-
-               let promises = featureGroups.map(featureGroupId =>
-                       new Promise(resolve =>
-                               FeatureGroupsActionHelper.fetchFeatureGroup(
-                                       dispatch, {licenseModelId: itemId, featureGroupId, version}
-                               ).then(featureGroup => resolve(featureGroup.name))
-                               .catch(reason => console.log(`getFeatureGroups Promise rejected ('${reason}')`))
-                       )
-               );
-
-               Promise.all(promises).then(fetchedGroups => {
-                       let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
-                       dispatch({
-                               type: actionTypes.DATA_PROCESSED,
-                               data: {
-                                       cid,
-                                       [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
-                               }
-                       });
-               });
-
-               return featureGroups;
-
-       },
-
-       getLicenseAgreements(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
-
-               let licenseAgreements = data[fieldName] || [];
-               if (!(licenseAgreements instanceof Array)) {
-                       licenseAgreements = [licenseAgreements];
-               }
-
-               let promises = licenseAgreements.map(licenseAgreementId =>
-                       new Promise(resolve =>
-                               LicenseAgreementActionHelper.fetchLicenseAgreement(
-                                       dispatch, {licenseModelId: itemId, licenseAgreementId, version}
-                               ).then(licenseAgreement => resolve(licenseAgreement.name))
-                               .catch(reason => console.log(`getLicenseAgreements Promise rejected ('${reason}')`))
-                       )
-               );
-
-               Promise.all(promises).then(fetchedAgreements => {
-                       let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
-                       dispatch({
-                               type: actionTypes.DATA_PROCESSED,
-                               data: {
-                                       cid,
-                                       [yoursOrTheirs]: { name: fieldName, value: fetchedAgreements }
-                               }
-                       });
-               });
-
-               return licenseAgreements;
-
-       },
-
-       processConflict(dispatch, {conflict, cid, version, itemId,}) {
-
-               let {id, type, yours, theirs} = conflict;
-
-               let newYours = MergeEditorActionHelper.createConflictObject(
-                       cloneDeep(yours), {cid, conflict, dispatch, itemId, version, isYours: true}
-               );
-               let newTheirs = MergeEditorActionHelper.createConflictObject(
-                       cloneDeep(theirs), {cid, conflict, dispatch, itemId, version, isYours: false}
-               );
-
-               return {
-                       id,
-                       type,
-                       yours: newYours,
-                       theirs: newTheirs
-               };
-
-       },
-
-       reduceList(data, {fieldName, args}) {
-
-               let {subField} = args;
-               return data[fieldName].map(el => el[subField]);
-
-       },
-
-       getEnumList({fieldName}) {
-
-               const enumLists = {
-                       'licenseTerm': laOptionsValues.LICENSE_MODEL_TYPE,
-                       'operationalScope': epOptionsValues.OPERATIONAL_SCOPE,
-                       'processType': processOptionValues.PROCESS_TYPE,
-                       'limitType': [
-                               {title: 'Service Provider', enum: 'ServiceProvider'},
-                               {title: 'Vendor', enum: 'Vendor'}
-                       ],
-                       'limitUnit': limitSelectValues.UNIT
-               };
-
-               return enumLists[fieldName];
-
-       },
-
-       getEnumValue(data, {fieldName, args = {}}) {
-
-               let value = data[fieldName];
-               let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
-               let enumValue = enumValues.find(el => el.enum === value);
-
-               return enumValue && enumValue.title || value;
-
-       },
-
-       processChoice(data, {fieldName, args = {}}) {
-
-               let value = data[fieldName];
-               let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
-               let newValue = value.other || enumValues && enumValues.find(el => el.enum === value.choice).title || value.choice;
-
-               return newValue;
-
-       },
-
-       processChoices(data, {fieldName, args = {}}) {
-
-               let value = data[fieldName];
-               let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
-               let newValue = value.other || getEnumValues({enums: enumValues, list: value.choices}) || value.choices;
-
-               return newValue;
-
-       },
-
-       convertArrayToObject(data, {fieldName}) {
-               let value = data[fieldName];
-               let newValue = {};
-               value.forEach((el, index) => {
-                       newValue[index] = el;
-               });
-               return newValue;
-       },
-
-       fetchCategory(data, {cid, isYours, fieldName, dispatch}) {
-
-               fetchCategories().then((categories) => {
-                       let value = createCategoryStr(data, {categories});
-                       let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
-
-                       dispatch({
-                               type: actionTypes.DATA_PROCESSED,
-                               data: {
-                                       cid,
-                                       [yoursOrTheirs]: { name: fieldName, value }
-                               }
-                       });
-
-               });
-       },
-
-       fetchLMVersion(data, {cid, dispatch, isYours}) {
-
-               let {licensingVersion, vendorId} = data;
-               let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
-
-               if (licensingVersion) {
-                       fetchVersion({licensingVersion, vendorId}).then(response => {
-                               dispatch({
-                                       type: actionTypes.DATA_PROCESSED,
-                                       data: {
-                                               cid,
-                                               [yoursOrTheirs]: {
-                                                       name: 'licensingVersion',
-                                                       value: response.name
-                                               }
-                                       }
-                               });
-                       });
-               }
-
-       },
-
-       parseDate(data, {fieldName}) {
-
-               let date = data[fieldName];
-               return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
-
-       }
-
+    analyzeSyncResult(dispatch, { itemId, version }) {
+        return ItemsHelper.checkItemStatus(dispatch, {
+            itemId,
+            versionId: version.id
+        }).then(response => {
+            let inMerge =
+                response &&
+                response.state &&
+                response.state.synchronizationState === SyncStates.MERGE;
+            if (inMerge) {
+                MergeEditorActionHelper.fetchConflicts(dispatch, {
+                    itemId,
+                    version
+                }).then(() =>
+                    dispatch({
+                        type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                        data: {
+                            modalComponentName: modalContentMapper.MERGE_EDITOR,
+                            modalClassName: 'merge-editor-modal',
+                            title: `${i18n('Merge Required')} - ${
+                                version.description
+                            }`,
+                            onDeclined: () => {
+                                dispatch({
+                                    type: modalActionTypes.GLOBAL_MODAL_CLOSE
+                                });
+                            },
+                            modalComponentProps: {
+                                size: 'lg',
+                                type: 'default'
+                            }
+                        }
+                    })
+                );
+            }
+            return Promise.resolve({
+                updatedVersion: response,
+                inMerge,
+                isDirty: response.state.dirty
+            });
+        });
+    },
+
+    fetchConflicts(dispatch, { itemId, version }) {
+        return fetchConflicts({ itemId, version }).then(data => {
+            dispatch({
+                type: actionTypes.LOAD_CONFLICTS,
+                data
+            });
+            return data;
+        });
+    },
+
+    fetchConflict(dispatch, { itemId, version, cid }) {
+        fetchConflictById({ itemId, version, cid }).then(data => {
+            let newData = {};
+            newData = MergeEditorActionHelper.processConflict(dispatch, {
+                conflict: data,
+                itemId,
+                cid,
+                version
+            });
+            dispatch({
+                type: actionTypes.LOAD_CONFLICT,
+                data: newData
+            });
+        });
+    },
+
+    resolveConflict(
+        dispatch,
+        { itemId, version, conflictId, resolution, currentScreen }
+    ) {
+        resolveConflict({ itemId, version, conflictId, resolution }).then(
+            () => {
+                MergeEditorActionHelper.fetchConflicts(dispatch, {
+                    itemId,
+                    version
+                }).then(conflicts => {
+                    if (
+                        conflicts.conflictInfoList &&
+                        conflicts.conflictInfoList.length === 0
+                    ) {
+                        dispatch({
+                            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+                        });
+                        ScreensHelper.loadLandingScreen(dispatch, {
+                            previousScreenName: currentScreen.screen,
+                            props: currentScreen.props
+                        });
+                        ItemsHelper.checkItemStatus(dispatch, {
+                            itemId,
+                            versionId: version.id
+                        });
+                    }
+                });
+            }
+        );
+    },
+
+    createConflictObject(
+        data,
+        { cid, conflict, dispatch, itemId, version, isYours }
+    ) {
+        let newData = {};
+
+        for (let key in data) {
+            if (data.hasOwnProperty(key)) {
+                let value = data[key];
+                let fieldRule =
+                    (dataRules[conflict.type] &&
+                        dataRules[conflict.type][key]) ||
+                    dataRules.general[key];
+
+                if (fieldRule) {
+                    switch (fieldRule.rule) {
+                        case rules.SKIP:
+                            break;
+
+                        case rules.BOOLEAN:
+                            let { trueValue, falseValue } = fieldRule;
+                            newData[key] =
+                                value === trueValue
+                                    ? true
+                                    : value === falseValue ? false : undefined;
+                            break;
+
+                        case rules.PARSE:
+                            let { moveFields, subFields } = fieldRule;
+                            if (moveFields) {
+                                let fields = subFields || Object.keys(value);
+                                fields.forEach(field => {
+                                    newData[
+                                        field
+                                    ] = MergeEditorActionHelper.createConflictObject(
+                                        value[field],
+                                        {
+                                            cid,
+                                            conflict,
+                                            dispatch,
+                                            itemId,
+                                            version,
+                                            isYours
+                                        }
+                                    );
+                                });
+                            } else {
+                                newData[
+                                    key
+                                ] = MergeEditorActionHelper.createConflictObject(
+                                    value,
+                                    {
+                                        cid,
+                                        conflict,
+                                        dispatch,
+                                        itemId,
+                                        version,
+                                        isYours
+                                    }
+                                );
+                            }
+                            break;
+
+                        case rules.FUNCTION:
+                            let { args, functionName } = fieldRule;
+                            newData[key] = MergeEditorActionHelper[
+                                functionName
+                            ](data, {
+                                cid,
+                                conflict,
+                                dispatch,
+                                version,
+                                fieldName: key,
+                                isYours,
+                                itemId,
+                                args
+                            });
+                            break;
+
+                        default:
+                            newData[key] = value;
+                            break;
+                    }
+                } else {
+                    newData[key] = value;
+                }
+            }
+        }
+
+        return newData;
+    },
+
+    getNamesFromIDs(
+        data,
+        { version, cid, dispatch, itemId, fieldName, isYours, args }
+    ) {
+        let idList = data[fieldName] || [];
+        let { fetchFunction, fetchField } = args;
+
+        let promises = idList.map(
+            id =>
+                new Promise(resolve =>
+                    MergeEditorActionHelper[fetchFunction](dispatch, {
+                        licenseModelId: itemId,
+                        [fetchField]: id,
+                        version
+                    }).then(item => resolve(item.name))
+                )
+        );
+
+        Promise.all(promises).then(fetchedItems => {
+            let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
+            dispatch({
+                type: actionTypes.DATA_PROCESSED,
+                data: {
+                    cid,
+                    [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
+                }
+            });
+        });
+
+        return idList;
+    },
+
+    getFeatureGroups(
+        data,
+        { version, cid, dispatch, itemId, fieldName, isYours }
+    ) {
+        let featureGroups = data[fieldName] || [];
+        if (!(featureGroups instanceof Array)) {
+            featureGroups = [featureGroups];
+        }
+
+        let promises = featureGroups.map(
+            featureGroupId =>
+                new Promise(resolve =>
+                    FeatureGroupsActionHelper.fetchFeatureGroup(dispatch, {
+                        licenseModelId: itemId,
+                        featureGroupId,
+                        version
+                    })
+                        .then(featureGroup => resolve(featureGroup.name))
+                        .catch(reason =>
+                            console.log(
+                                `getFeatureGroups Promise rejected ('${reason}')`
+                            )
+                        )
+                )
+        );
+
+        Promise.all(promises).then(fetchedGroups => {
+            let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
+            dispatch({
+                type: actionTypes.DATA_PROCESSED,
+                data: {
+                    cid,
+                    [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
+                }
+            });
+        });
+
+        return featureGroups;
+    },
+
+    getLicenseAgreements(
+        data,
+        { version, cid, dispatch, itemId, fieldName, isYours }
+    ) {
+        let licenseAgreements = data[fieldName] || [];
+        if (!(licenseAgreements instanceof Array)) {
+            licenseAgreements = [licenseAgreements];
+        }
+
+        let promises = licenseAgreements.map(
+            licenseAgreementId =>
+                new Promise(resolve =>
+                    LicenseAgreementActionHelper.fetchLicenseAgreement(
+                        dispatch,
+                        {
+                            licenseModelId: itemId,
+                            licenseAgreementId,
+                            version
+                        }
+                    )
+                        .then(licenseAgreement =>
+                            resolve(licenseAgreement.name)
+                        )
+                        .catch(reason =>
+                            console.log(
+                                `getLicenseAgreements Promise rejected ('${reason}')`
+                            )
+                        )
+                )
+        );
+
+        Promise.all(promises).then(fetchedAgreements => {
+            let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
+            dispatch({
+                type: actionTypes.DATA_PROCESSED,
+                data: {
+                    cid,
+                    [yoursOrTheirs]: {
+                        name: fieldName,
+                        value: fetchedAgreements
+                    }
+                }
+            });
+        });
+
+        return licenseAgreements;
+    },
+
+    processConflict(dispatch, { conflict, cid, version, itemId }) {
+        let { id, type, yours, theirs } = conflict;
+
+        let newYours = MergeEditorActionHelper.createConflictObject(
+            cloneDeep(yours),
+            { cid, conflict, dispatch, itemId, version, isYours: true }
+        );
+        let newTheirs = MergeEditorActionHelper.createConflictObject(
+            cloneDeep(theirs),
+            { cid, conflict, dispatch, itemId, version, isYours: false }
+        );
+
+        return {
+            id,
+            type,
+            yours: newYours,
+            theirs: newTheirs
+        };
+    },
+
+    reduceList(data, { fieldName, args }) {
+        let { subField } = args;
+        return data[fieldName].map(el => el[subField]);
+    },
+
+    getEnumList({ fieldName }) {
+        const enumLists = {
+            licenseTerm: laOptionsValues.LICENSE_MODEL_TYPE,
+            operationalScope: epOptionsValues.OPERATIONAL_SCOPE,
+            processType: processOptionValues.PROCESS_TYPE,
+            limitType: [
+                { title: 'Service Provider', enum: 'ServiceProvider' },
+                { title: 'Vendor', enum: 'Vendor' }
+            ],
+            limitUnit: limitSelectValues.UNIT
+        };
+
+        return enumLists[fieldName];
+    },
+
+    getEnumValue(data, { fieldName, args = {} }) {
+        let value = data[fieldName];
+        let enumValues = MergeEditorActionHelper.getEnumList({
+            fieldName: args.listName || fieldName
+        });
+        let enumValue = enumValues.find(el => el.enum === value);
+
+        return (enumValue && enumValue.title) || value;
+    },
+
+    processChoice(data, { fieldName, args = {} }) {
+        let value = data[fieldName];
+        let enumValues = MergeEditorActionHelper.getEnumList({
+            fieldName: args.listName || fieldName
+        });
+        let newValue =
+            value.other ||
+            (enumValues &&
+                enumValues.find(el => el.enum === value.choice).title) ||
+            value.choice;
+
+        return newValue;
+    },
+
+    processChoices(data, { fieldName, args = {} }) {
+        let value = data[fieldName];
+        let enumValues = MergeEditorActionHelper.getEnumList({
+            fieldName: args.listName || fieldName
+        });
+        let newValue =
+            value.other ||
+            getEnumValues({ enums: enumValues, list: value.choices }) ||
+            value.choices;
+
+        return newValue;
+    },
+
+    convertArrayToObject(data, { fieldName }) {
+        let value = data[fieldName];
+        let newValue = {};
+        value.forEach((el, index) => {
+            newValue[index] = el;
+        });
+        return newValue;
+    },
+
+    fetchCategory(data, { cid, isYours, fieldName, dispatch }) {
+        fetchCategories().then(categories => {
+            let value = createCategoryStr(data, { categories });
+            let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
+
+            dispatch({
+                type: actionTypes.DATA_PROCESSED,
+                data: {
+                    cid,
+                    [yoursOrTheirs]: { name: fieldName, value }
+                }
+            });
+        });
+    },
+
+    fetchLMVersion(data, { cid, dispatch, isYours }) {
+        let { licensingVersion, vendorId } = data;
+        let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
+
+        if (licensingVersion) {
+            fetchVersion({ licensingVersion, vendorId }).then(response => {
+                dispatch({
+                    type: actionTypes.DATA_PROCESSED,
+                    data: {
+                        cid,
+                        [yoursOrTheirs]: {
+                            name: 'licensingVersion',
+                            value: response.name
+                        }
+                    }
+                });
+            });
+        }
+    },
+
+    parseDate(data, { fieldName }) {
+        let date = data[fieldName];
+        return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
+    }
 };
 
 export default MergeEditorActionHelper;
index f7f6d41..b82d086 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       LOAD_CONFLICTS: null,
-       ADD_ACTIONS: null,
-       LOAD_CONFLICT: null,
-       DATA_PROCESSED: null
+    LOAD_CONFLICTS: null,
+    ADD_ACTIONS: null,
+    LOAD_CONFLICT: null,
+    DATA_PROCESSED: null
 });
 
 export const rules = {
-       SKIP: 'skip',
-       PARSE: 'parse',
-       FUNCTION: 'function',
-       BOOLEAN: 'boolean'
+    SKIP: 'skip',
+    PARSE: 'parse',
+    FUNCTION: 'function',
+    BOOLEAN: 'boolean'
 };
 
 export const SyncStates = {
-       MERGE : 'Merging',
-       OUT_OF_SYNC: 'OutOfSync',
-       UP_TO_DATE: 'UpToDate'
+    MERGE: 'Merging',
+    OUT_OF_SYNC: 'OutOfSync',
+    UP_TO_DATE: 'UpToDate'
 };
 
 export const ResolutionTypes = {
-       YOURS: 'YOURS',
-       THEIRS: 'THEIRS'
+    YOURS: 'YOURS',
+    THEIRS: 'THEIRS'
 };
 
 export const fileTypes = {
-       LKG : 'LicenseKeyGroup',
-       VLM : 'VendorLicenseModel',
-       EP  : 'EntitlementPool',
-       FG  : 'FeatureGroup',
-       LA  : 'LicenseAgreement',
-       VSP : 'VendorSoftwareProduct',
-       LIMIT : 'Limit',
-       VSP_Q : 'VSPQuestionnaire',
-       COMPONENT : 'Component',
-       COMPONENT_Q : 'ComponentQuestionnaire',
-       COMPONENT_DEP : 'ComponentDependencies',
-       COMPUTE_Q : 'ComputeQuestionnaire',
-       COMPUTE : 'Compute',
-       COMPUTE_FLAVOR: 'ComputeFlavor',
-       NIC : 'Nic',
-       NIC_Q : 'NicQuestionnaire',
-       IMAGE : 'Image',
-       IMAGE_Q : 'ImageQuestionnaire',
-       PROCESS : 'Process',
-       DEPLOYMENT_FLAVOR : 'DeploymentFlavor',
-       VENDOR : 'Vendor',
-       NETWORK : 'Network',
-       ORCHESTRATION_TEMPLATE_CANDIDATE : 'OrchestrationTemplateCandidate'
+    LKG: 'LicenseKeyGroup',
+    VLM: 'VendorLicenseModel',
+    EP: 'EntitlementPool',
+    FG: 'FeatureGroup',
+    LA: 'LicenseAgreement',
+    VSP: 'VendorSoftwareProduct',
+    LIMIT: 'Limit',
+    VSP_Q: 'VSPQuestionnaire',
+    COMPONENT: 'Component',
+    COMPONENT_Q: 'ComponentQuestionnaire',
+    COMPONENT_DEP: 'ComponentDependencies',
+    COMPUTE_Q: 'ComputeQuestionnaire',
+    COMPUTE: 'Compute',
+    COMPUTE_FLAVOR: 'ComputeFlavor',
+    NIC: 'Nic',
+    NIC_Q: 'NicQuestionnaire',
+    IMAGE: 'Image',
+    IMAGE_Q: 'ImageQuestionnaire',
+    PROCESS: 'Process',
+    DEPLOYMENT_FLAVOR: 'DeploymentFlavor',
+    VENDOR: 'Vendor',
+    NETWORK: 'Network',
+    ORCHESTRATION_TEMPLATE_CANDIDATE: 'OrchestrationTemplateCandidate'
 };
 
 export const dataRules = {
-       general: {
-               id: {
-                       rule: rules.SKIP
-               },
-               questionareData: {
-                       rule: rules.PARSE,
-                       moveFields: true
-               },
-               startDate: {
-                       rule: rules.FUNCTION,
-                       functionName: 'parseDate'
-               },
-               expiryDate: {
-                       rule: rules.FUNCTION,
-                       functionName: 'parseDate'
-               },
-               featureGroups: {
-                       rule: rules.FUNCTION,
-                       functionName: 'reduceList',
-                       args: {subField: 'name'}
-               },
-               licenseKeyGroups: {
-                       rule: rules.FUNCTION,
-                       functionName: 'reduceList',
-                       args: {subField: 'name'}
-               },
-               entitlementPools: {
-                       rule: rules.FUNCTION,
-                       functionName: 'reduceList',
-                       args: {subField: 'name'}
-               },
-       },
-       [fileTypes.COMPONENT] : {
-       },
-       [fileTypes.COMPUTE_FLAVOR] : {
-               associatedToDeploymentFlavor: {
-                       rule: rules.BOOLEAN,
-                       trueValue: 'true'
-               }
-       },
-       [fileTypes.COMPUTE_Q] : {
-       },
-       [fileTypes.COMPONENT_Q] : {
-               isComponentMandatory: {
-                       rule: rules.BOOLEAN,
-                       trueValue: 'YES',
-                       falseValue: 'NO'
-               }
-       },
-       [fileTypes.EP] : {
-               referencingFeatureGroups: {
-                       rule: rules.SKIP,
-                       functionName: 'getFeatureGroups'
-               },
-               operationalScope: {
-                       rule: rules.FUNCTION,
-                       functionName: 'processChoices'
-               },
-       },
-       [fileTypes.FG] : {
-               referencingLicenseAgreements: {
-                       rule: rules.SKIP,
-                       functionName: 'getLicenseAgreements'
-               }
-       },
-       [fileTypes.LA] : {
-               licenseTerm : {
-                       rule: rules.FUNCTION,
-                       functionName: 'processChoice'
-               }
-       },
-       [fileTypes.LIMIT] : {
-               type: {
-                       rule: rules.FUNCTION,
-                       functionName: 'getEnumValue',
-                       args: {listName: 'limitType'}
-               },
-               unit: {
-                       rule: rules.FUNCTION,
-                       functionName: 'getEnumValue',
-                       args: {listName: 'limitUnit'}
-               }
-       },
-       [fileTypes.LKG] : {
-               operationalScope: {
-                       rule: rules.FUNCTION,
-                       functionName: 'processChoices'
-               },
-               referencingFeatureGroups: {
-                       rule: rules.SKIP,
-                       functionName: 'getFeatureGroups'
-               },
-       },
-       [fileTypes.NIC] : {
-               networkId: {
-                       rule: rules.SKIP
-               }
-       },
-       [fileTypes.NIC_Q] : {
-       },
-       [fileTypes.PROCESS] : {
-               type: {
-                       rule: rules.FUNCTION,
-                       functionName: 'getEnumValue',
-                       args: {listName: 'processType'}
-               }
-       },
-       [fileTypes.VLM] : {
-               iconRef: {
-                       rule: rules.SKIP
-               }
-       },
-       [fileTypes.VSP] : {
-               vendorId: {
-                       rule: rules.SKIP
-               },
-               onboardingMethod: {
-                       rule: rules.SKIP
-               },
-               validationData: {
-                       rule: rules.SKIP
-               },
-               isOldVersion: {
-                       rule: rules.SKIP
-               },
-               licensingVersion: {
-                       rule: rules.FUNCTION,
-                       functionName: 'fetchLMVersion'
-               },
-               category: {
-                       rule: rules.FUNCTION,
-                       functionName: 'fetchCategory'
-               },
-               subCategory: {
-                       rule: rules.SKIP
-               },
-       },
-       [fileTypes.VSP_Q] : {
-               affinityData: {
-                       rule: rules.SKIP
-               },
-               storageReplicationAcrossRegion: {
-                       rule: rules.BOOLEAN,
-                       trueValue: 'true',
-                       falseValue: 'false'
-               }
-       },
-       [fileTypes.ORCHESTRATION_TEMPLATE_CANDIDATE] : {
-               modules: {
-                       rule: rules.FUNCTION,
-                       functionName: 'convertArrayToObject'
-               },
-       },
+    general: {
+        id: {
+            rule: rules.SKIP
+        },
+        questionareData: {
+            rule: rules.PARSE,
+            moveFields: true
+        },
+        startDate: {
+            rule: rules.FUNCTION,
+            functionName: 'parseDate'
+        },
+        expiryDate: {
+            rule: rules.FUNCTION,
+            functionName: 'parseDate'
+        },
+        featureGroups: {
+            rule: rules.FUNCTION,
+            functionName: 'reduceList',
+            args: { subField: 'name' }
+        },
+        licenseKeyGroups: {
+            rule: rules.FUNCTION,
+            functionName: 'reduceList',
+            args: { subField: 'name' }
+        },
+        entitlementPools: {
+            rule: rules.FUNCTION,
+            functionName: 'reduceList',
+            args: { subField: 'name' }
+        }
+    },
+    [fileTypes.COMPONENT]: {},
+    [fileTypes.COMPUTE_FLAVOR]: {
+        associatedToDeploymentFlavor: {
+            rule: rules.BOOLEAN,
+            trueValue: 'true'
+        }
+    },
+    [fileTypes.COMPUTE_Q]: {},
+    [fileTypes.COMPONENT_Q]: {
+        isComponentMandatory: {
+            rule: rules.BOOLEAN,
+            trueValue: 'YES',
+            falseValue: 'NO'
+        }
+    },
+    [fileTypes.EP]: {
+        referencingFeatureGroups: {
+            rule: rules.SKIP,
+            functionName: 'getFeatureGroups'
+        },
+        operationalScope: {
+            rule: rules.FUNCTION,
+            functionName: 'processChoices'
+        }
+    },
+    [fileTypes.FG]: {
+        referencingLicenseAgreements: {
+            rule: rules.SKIP,
+            functionName: 'getLicenseAgreements'
+        }
+    },
+    [fileTypes.LA]: {
+        licenseTerm: {
+            rule: rules.FUNCTION,
+            functionName: 'processChoice'
+        }
+    },
+    [fileTypes.LIMIT]: {
+        type: {
+            rule: rules.FUNCTION,
+            functionName: 'getEnumValue',
+            args: { listName: 'limitType' }
+        },
+        unit: {
+            rule: rules.FUNCTION,
+            functionName: 'getEnumValue',
+            args: { listName: 'limitUnit' }
+        }
+    },
+    [fileTypes.LKG]: {
+        operationalScope: {
+            rule: rules.FUNCTION,
+            functionName: 'processChoices'
+        },
+        referencingFeatureGroups: {
+            rule: rules.SKIP,
+            functionName: 'getFeatureGroups'
+        }
+    },
+    [fileTypes.NIC]: {
+        networkId: {
+            rule: rules.SKIP
+        }
+    },
+    [fileTypes.NIC_Q]: {},
+    [fileTypes.PROCESS]: {
+        type: {
+            rule: rules.FUNCTION,
+            functionName: 'getEnumValue',
+            args: { listName: 'processType' }
+        }
+    },
+    [fileTypes.VLM]: {
+        iconRef: {
+            rule: rules.SKIP
+        }
+    },
+    [fileTypes.VSP]: {
+        vendorId: {
+            rule: rules.SKIP
+        },
+        onboardingMethod: {
+            rule: rules.SKIP
+        },
+        validationData: {
+            rule: rules.SKIP
+        },
+        isOldVersion: {
+            rule: rules.SKIP
+        },
+        licensingVersion: {
+            rule: rules.FUNCTION,
+            functionName: 'fetchLMVersion'
+        },
+        category: {
+            rule: rules.FUNCTION,
+            functionName: 'fetchCategory'
+        },
+        subCategory: {
+            rule: rules.SKIP
+        }
+    },
+    [fileTypes.VSP_Q]: {
+        affinityData: {
+            rule: rules.SKIP
+        },
+        storageReplicationAcrossRegion: {
+            rule: rules.BOOLEAN,
+            trueValue: 'true',
+            falseValue: 'false'
+        }
+    },
+    [fileTypes.ORCHESTRATION_TEMPLATE_CANDIDATE]: {
+        modules: {
+            rule: rules.FUNCTION,
+            functionName: 'convertArrayToObject'
+        }
+    }
 };
index 6985fcf..1630849 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './MergeEditorConstants.js';
+import { actionTypes } from './MergeEditorConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.LOAD_CONFLICT: {
-                       let cdata = {...action.data};
-                       // let data = state.conflicts ? {...state.conflicts.data} : {} ;
-                       // data[cdata.id] = cdata;
-                       let conflicts = state.conflicts ? {...state.conflicts} : {};
-                       conflicts[cdata.id] = cdata;
-                       return {
-                               ...state,
-                               conflicts
-                       };
-               }
-               case actionTypes.DATA_PROCESSED: {
-                       let conflicts = {...state.conflicts};
-                       let {data} = action;
-                       if (data && data.cid) {
-                               let yours = {...conflicts[data.cid].yours};
-                               let theirs = {...conflicts[data.cid].theirs};
-                               let {yoursField, theirsField} = data;
-                               if (yoursField) {
-                                       yours[yoursField.name] = yoursField.value;
-                                       conflicts[data.cid].yours = yours;
-                               }
-                               if (theirsField) {
-                                       theirs[theirsField.name] = theirsField.value;
-                                       conflicts[data.cid].theirs = theirs;
-                               }
-                       }
-                       return {
-                               ...state,
-                               conflicts: {
-                                       ...conflicts
-                               }
-                       };
-               }
-               case actionTypes.LOAD_CONFLICTS:
-                       let conflictFiles = [];
-                       if (action.data) {
-                               conflictFiles = [...action.data.conflictInfoList];
-                       }
-                       return {
-                               inMerge: conflictFiles.length > 0,
-                               conflictFiles
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.LOAD_CONFLICT: {
+            let cdata = { ...action.data };
+            // let data = state.conflicts ? {...state.conflicts.data} : {} ;
+            // data[cdata.id] = cdata;
+            let conflicts = state.conflicts ? { ...state.conflicts } : {};
+            conflicts[cdata.id] = cdata;
+            return {
+                ...state,
+                conflicts
+            };
+        }
+        case actionTypes.DATA_PROCESSED: {
+            let conflicts = { ...state.conflicts };
+            let { data } = action;
+            if (data && data.cid) {
+                let yours = { ...conflicts[data.cid].yours };
+                let theirs = { ...conflicts[data.cid].theirs };
+                let { yoursField, theirsField } = data;
+                if (yoursField) {
+                    yours[yoursField.name] = yoursField.value;
+                    conflicts[data.cid].yours = yours;
+                }
+                if (theirsField) {
+                    theirs[theirsField.name] = theirsField.value;
+                    conflicts[data.cid].theirs = theirs;
+                }
+            }
+            return {
+                ...state,
+                conflicts: {
+                    ...conflicts
+                }
+            };
+        }
+        case actionTypes.LOAD_CONFLICTS:
+            let conflictFiles = [];
+            if (action.data) {
+                conflictFiles = [...action.data.conflictInfoList];
+            }
+            return {
+                inMerge: conflictFiles.length > 0,
+                conflictFiles
+            };
+        default:
+            return state;
+    }
 };
index 34d8641..a7e36a3 100644 (file)
@@ -24,233 +24,389 @@ import GridItem from 'nfvo-components/grid/GridItem.jsx';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import Radio from 'sdc-ui/lib/react/Radio.js';
 import equal from 'deep-equal';
-import {ResolutionTypes} from './MergeEditorConstants.js';
+import { ResolutionTypes } from './MergeEditorConstants.js';
 
-class ConflictCategory extends React.Component  {
-       state = {
-               resolution: ResolutionTypes.YOURS
-       };
+class ConflictCategory extends React.Component {
+    state = {
+        resolution: ResolutionTypes.YOURS
+    };
 
-       getTitle(conflictType, conflictName) {
-               if (typeof conflictName === 'undefined' || conflictType === conflictName) {
-                       return i18n(conflictType);
-               } else {
-                       return `${i18n(conflictType)}: ${conflictName}`;
-               }
-       }
+    getTitle(conflictType, conflictName) {
+        if (
+            typeof conflictName === 'undefined' ||
+            conflictType === conflictName
+        ) {
+            return i18n(conflictType);
+        } else {
+            return `${i18n(conflictType)}: ${conflictName}`;
+        }
+    }
 
-       render() {
-               let {collapseExpand, conflict: {id: conflictId, type, name}, isCollapsed, item: {id: itemId, version}, onResolveConflict} = this.props;
-               let {resolution} = this.state;
-               const iconClass = isCollapsed ? 'merge-chevron' : 'merge-chevron right';
+    render() {
+        let {
+            collapseExpand,
+            conflict: { id: conflictId, type, name },
+            isCollapsed,
+            item: { id: itemId, version },
+            onResolveConflict
+        } = this.props;
+        let { resolution } = this.state;
+        const iconClass = isCollapsed ? 'merge-chevron' : 'merge-chevron right';
 
-               return (
-                       <div key={'conflictCategory_' + conflictId}  >
-                               <GridSection className='conflict-section'>
-                                       <GridItem >
-                                               <div className='collapsible-section' onClick={collapseExpand}>
-                                                       <SVGIcon name={isCollapsed ? 'chevronDown' : 'chevronUp'} iconClassName={iconClass} />
-                                                       <div className='conflict-title'>{this.getTitle(type, name)}</div>
-                                               </div>
-                                       </GridItem>
-                                       <GridItem className='yours'>
-                                               <Radio name={'radio_' + conflictId} checked={resolution === ResolutionTypes.YOURS} value='yours'
-                                                          onChange={() => this.setState({resolution: ResolutionTypes.YOURS})} data-test-id={'radio_' + conflictId + '_yours'} />
-                                       </GridItem>
-                                       <GridItem className='theirs'>
-                                               <Radio name={'radio_' + conflictId} checked={resolution === ResolutionTypes.THEIRS} value='theirs'
-                                                          onChange={() => this.setState({resolution: ResolutionTypes.THEIRS})} data-test-id={'radio_' + conflictId + '_theirs'} /></GridItem>
-                                       <GridItem className='resolve'>
-                                               <Button className='conflict-resolve-btn' btnType='outline' color='gray'
-                                                       onClick={() => onResolveConflict({conflictId, resolution, itemId, version})}>
-                                                       {i18n('Resolve')}
-                                               </Button>
-                                       </GridItem>
-                               </GridSection>
-                               <div>
-                                       {isCollapsed && this.props.children}
-                               </div>
-                       </div>
-               );
-       }
-
-};
-
-class TextCompare extends React.Component  {
-       render() {
-               // let rand = Math.random() * (3000 - 1) + 1;
-               let {yours, theirs, field, type, isObjName, conflictsOnly} = this.props;
-               let typeYours = typeof yours;
-               let typeTheirs = typeof theirs;
+        return (
+            <div key={'conflictCategory_' + conflictId}>
+                <GridSection className="conflict-section">
+                    <GridItem>
+                        <div
+                            className="collapsible-section"
+                            onClick={collapseExpand}>
+                            <SVGIcon
+                                name={isCollapsed ? 'chevronDown' : 'chevronUp'}
+                                iconClassName={iconClass}
+                            />
+                            <div className="conflict-title">
+                                {this.getTitle(type, name)}
+                            </div>
+                        </div>
+                    </GridItem>
+                    <GridItem className="yours">
+                        <Radio
+                            name={'radio_' + conflictId}
+                            checked={resolution === ResolutionTypes.YOURS}
+                            value="yours"
+                            onChange={() =>
+                                this.setState({
+                                    resolution: ResolutionTypes.YOURS
+                                })
+                            }
+                            data-test-id={'radio_' + conflictId + '_yours'}
+                        />
+                    </GridItem>
+                    <GridItem className="theirs">
+                        <Radio
+                            name={'radio_' + conflictId}
+                            checked={resolution === ResolutionTypes.THEIRS}
+                            value="theirs"
+                            onChange={() =>
+                                this.setState({
+                                    resolution: ResolutionTypes.THEIRS
+                                })
+                            }
+                            data-test-id={'radio_' + conflictId + '_theirs'}
+                        />
+                    </GridItem>
+                    <GridItem className="resolve">
+                        <Button
+                            className="conflict-resolve-btn"
+                            btnType="outline"
+                            color="gray"
+                            onClick={() =>
+                                onResolveConflict({
+                                    conflictId,
+                                    resolution,
+                                    itemId,
+                                    version
+                                })
+                            }>
+                            {i18n('Resolve')}
+                        </Button>
+                    </GridItem>
+                </GridSection>
+                <div>{isCollapsed && this.props.children}</div>
+            </div>
+        );
+    }
+}
 
-               let parsedType = `${type}/${field}`.replace(/\/[0-9]+/g,'/index');
-               let level = type.split('/').length;
+class TextCompare extends React.Component {
+    render() {
+        // let rand = Math.random() * (3000 - 1) + 1;
+        let {
+            yours,
+            theirs,
+            field,
+            type,
+            isObjName,
+            conflictsOnly
+        } = this.props;
+        let typeYours = typeof yours;
+        let typeTheirs = typeof theirs;
 
-               if (typeYours === 'boolean' || typeTheirs === 'boolean') {
-                       yours = yours ? i18n('Yes') : i18n('No');
-                       theirs = theirs ? i18n('Yes') : i18n('No');
-               }
+        let parsedType = `${type}/${field}`.replace(/\/[0-9]+/g, '/index');
+        let level = type.split('/').length;
 
+        if (typeYours === 'boolean' || typeTheirs === 'boolean') {
+            yours = yours ? i18n('Yes') : i18n('No');
+            theirs = theirs ? i18n('Yes') : i18n('No');
+        }
 
-               /*if ((typeYours !== 'string' && typeYours !== 'undefined') || (typeTheirs !== 'string' && typeTheirs !== 'undefined')) {
+        /*if ((typeYours !== 'string' && typeYours !== 'undefined') || (typeTheirs !== 'string' && typeTheirs !== 'undefined')) {
                        return (<div className='merge-editor-text-field field-error'>{field} cannot be parsed for display</div>);
                }*/
-               let isDiff = yours !== theirs;
-               if (!isObjName &&
-                       ((!isDiff && conflictsOnly) ||
-                        (yours === '' && theirs === '') ||
-                        (typeYours === 'undefined' && typeTheirs === 'undefined')
-                       )
-               ) {
-                       return null;
-               }
+        let isDiff = yours !== theirs;
+        if (
+            !isObjName &&
+            ((!isDiff && conflictsOnly) ||
+                (yours === '' && theirs === '') ||
+                (typeYours === 'undefined' && typeTheirs === 'undefined'))
+        ) {
+            return null;
+        }
 
-               return (
-                       <GridSection className={isDiff ? 'merge-editor-text-field diff' : 'merge-editor-text-field'}>
-                               <GridItem className='field-col grid-col-title' stretch>
-                                       <div className={`field ${isDiff ? 'diff' : ''} field-name level-${level} ${isObjName ? 'field-object-name' : ''}`}>
-                                               {i18n(parsedType)}
-                                       </div>
-                               </GridItem>
-                               <GridItem className='field-col grid-col-yours' stretch>
-                                       <div className={`field field-yours ${!yours ? 'empty-field' : ''}`} >{yours || (isObjName ? '' : '━━')}</div>
-                               </GridItem>
-                               <GridItem className='field-col grid-col-theirs' stretch>
-                                       <div className={`field field-theirs ${!theirs ? 'empty-field' : ''}`}>{theirs || (isObjName ? '' : '━━')}</div>
-                               </GridItem>
-                               <GridItem stretch/>
-                       </GridSection>
-               );
-       }
-};
+        return (
+            <GridSection
+                className={
+                    isDiff
+                        ? 'merge-editor-text-field diff'
+                        : 'merge-editor-text-field'
+                }>
+                <GridItem className="field-col grid-col-title" stretch>
+                    <div
+                        className={`field ${
+                            isDiff ? 'diff' : ''
+                        } field-name level-${level} ${
+                            isObjName ? 'field-object-name' : ''
+                        }`}>
+                        {i18n(parsedType)}
+                    </div>
+                </GridItem>
+                <GridItem className="field-col grid-col-yours" stretch>
+                    <div
+                        className={`field field-yours ${
+                            !yours ? 'empty-field' : ''
+                        }`}>
+                        {yours || (isObjName ? '' : '━━')}
+                    </div>
+                </GridItem>
+                <GridItem className="field-col grid-col-theirs" stretch>
+                    <div
+                        className={`field field-theirs ${
+                            !theirs ? 'empty-field' : ''
+                        }`}>
+                        {theirs || (isObjName ? '' : '━━')}
+                    </div>
+                </GridItem>
+                <GridItem stretch />
+            </GridSection>
+        );
+    }
+}
 
 class MergeEditorView extends React.Component {
-       state = {
-               collapsingSections: {},
-               conflictsOnly: false
-       };
+    state = {
+        collapsingSections: {},
+        conflictsOnly: false
+    };
 
-       render() {
-               let {conflicts, item, conflictFiles, onResolveConflict, currentScreen, resolution} = this.props;
+    render() {
+        let {
+            conflicts,
+            item,
+            conflictFiles,
+            onResolveConflict,
+            currentScreen,
+            resolution
+        } = this.props;
 
-               return (
-               <div className='merge-editor'>
-                       {conflictFiles && this.renderConflictTableTitles()}
-                       <div className='merge-editor-body'>
-                               {conflictFiles && conflictFiles.sort((a, b) => a.type > b.type).map(file => (
-                               <ConflictCategory key={'conflict_' + file.id} conflict={file} item={item} isCollapsed={this.state.collapsingSections[file.id]}
-                                       collapseExpand={()=>{this.updateCollapseState(file.id);}}
-                                       onResolveConflict={cDetails => onResolveConflict({...cDetails, currentScreen})}>
-                                       {(conflicts && conflicts[file.id]) &&
-                                               this.getUnion(conflicts[file.id].yours, conflicts[file.id].theirs).map(field => {
-                                                       return this.renderField(field, file, conflicts[file.id].yours[field], conflicts[file.id].theirs[field], resolution);
-                                               })}
-                               </ConflictCategory>))}
-                       </div>
-               </div>);
-       }
+        return (
+            <div className="merge-editor">
+                {conflictFiles && this.renderConflictTableTitles()}
+                <div className="merge-editor-body">
+                    {conflictFiles &&
+                        conflictFiles
+                            .sort((a, b) => a.type > b.type)
+                            .map(file => (
+                                <ConflictCategory
+                                    key={'conflict_' + file.id}
+                                    conflict={file}
+                                    item={item}
+                                    isCollapsed={
+                                        this.state.collapsingSections[file.id]
+                                    }
+                                    collapseExpand={() => {
+                                        this.updateCollapseState(file.id);
+                                    }}
+                                    onResolveConflict={cDetails =>
+                                        onResolveConflict({
+                                            ...cDetails,
+                                            currentScreen
+                                        })
+                                    }>
+                                    {conflicts &&
+                                        conflicts[file.id] &&
+                                        this.getUnion(
+                                            conflicts[file.id].yours,
+                                            conflicts[file.id].theirs
+                                        ).map(field => {
+                                            return this.renderField(
+                                                field,
+                                                file,
+                                                conflicts[file.id].yours[field],
+                                                conflicts[file.id].theirs[
+                                                    field
+                                                ],
+                                                resolution
+                                            );
+                                        })}
+                                </ConflictCategory>
+                            ))}
+                </div>
+            </div>
+        );
+    }
 
-       renderConflictTableTitles()
-       {
-               return (<GridSection className='conflict-titles-section'>
-                       <GridItem>
-                               {i18n('Page')}
-                       </GridItem>
-                       <GridItem className='yours'>
-                               {i18n('Local (Me)')}
-                       </GridItem>
-                       <GridItem className='theirs'>
-                               {i18n('Last Committed')}
-                       </GridItem>
-                       <GridItem className='resolve'>
-                               <Input
-                                       label={i18n('Show Conflicts Only')}
-                                       type='checkbox'
-                                       value={this.state.conflictsOnly}
-                                       onChange={e => this.setState({conflictsOnly: e}) } />
-                       </GridItem>
-               </GridSection>);
-       }
-       // <Checkbox
-       //      label={i18n('Show Conflicts Only')}
-       //      value={this.state.conflictsOnly}
-       //      checked={this.state.conflictsOnly}
-       //      onChange={checked => this.setState({conflictsOnly: checked})} />
+    renderConflictTableTitles() {
+        return (
+            <GridSection className="conflict-titles-section">
+                <GridItem>{i18n('Page')}</GridItem>
+                <GridItem className="yours">{i18n('Local (Me)')}</GridItem>
+                <GridItem className="theirs">{i18n('Last Committed')}</GridItem>
+                <GridItem className="resolve">
+                    <Input
+                        label={i18n('Show Conflicts Only')}
+                        type="checkbox"
+                        value={this.state.conflictsOnly}
+                        onChange={e => this.setState({ conflictsOnly: e })}
+                    />
+                </GridItem>
+            </GridSection>
+        );
+    }
+    // <Checkbox
+    //         label={i18n('Show Conflicts Only')}
+    //         value={this.state.conflictsOnly}
+    //         checked={this.state.conflictsOnly}
+    //         onChange={checked => this.setState({conflictsOnly: checked})} />
 
-       renderObjects(yours, theirs, fileType, field, id, resolution) {
-               if (equal(yours, theirs)) {
-                       return;
-               }
-               let {conflictsOnly} = this.state;
-               return (
-                       <div key={`obj_${fileType}/${field}_${id}`}>
-                               <TextCompare field={field} type={fileType} conflictsOnly={conflictsOnly} yours='' theirs='' isObjName resolution={resolution} />
-                               <div className='field-objects'>
-                                       <div>
-                                               {this.getUnion(yours, theirs).map(key =>
-                                                       this.renderField(
-                                                               key,
-                                                               {type: `${fileType}/${field}`, id},
-                                                               yours && yours[key],
-                                                               theirs && theirs[key]
-                                                       )
-                                               )}
-                                       </div>
-                               </div>
-                       </div>
-               );
-       }
+    renderObjects(yours, theirs, fileType, field, id, resolution) {
+        if (equal(yours, theirs)) {
+            return;
+        }
+        let { conflictsOnly } = this.state;
+        return (
+            <div key={`obj_${fileType}/${field}_${id}`}>
+                <TextCompare
+                    field={field}
+                    type={fileType}
+                    conflictsOnly={conflictsOnly}
+                    yours=""
+                    theirs=""
+                    isObjName
+                    resolution={resolution}
+                />
+                <div className="field-objects">
+                    <div>
+                        {this.getUnion(yours, theirs).map(key =>
+                            this.renderField(
+                                key,
+                                { type: `${fileType}/${field}`, id },
+                                yours && yours[key],
+                                theirs && theirs[key]
+                            )
+                        )}
+                    </div>
+                </div>
+            </div>
+        );
+    }
 
-       renderList(yours = [], theirs = [], type, field, id, resolution) {
-               let theirsList = theirs.join(', ');
-               let yoursList = yours.join(', ');
-               let {conflictsOnly} = this.state;
-               return (<TextCompare key={'text_' + id + '_' + field}
-                        field={field} type={type} yours={yoursList} theirs={theirsList} conflictsOnly={conflictsOnly} resolution={resolution} />);
-       }
+    renderList(yours = [], theirs = [], type, field, id, resolution) {
+        let theirsList = theirs.join(', ');
+        let yoursList = yours.join(', ');
+        let { conflictsOnly } = this.state;
+        return (
+            <TextCompare
+                key={'text_' + id + '_' + field}
+                field={field}
+                type={type}
+                yours={yoursList}
+                theirs={theirsList}
+                conflictsOnly={conflictsOnly}
+                resolution={resolution}
+            />
+        );
+    }
 
-       renderField(field, file, yours, theirs, resolution) {
-               if (yours) {
-                       if (Array.isArray(yours)) {
-                               return this.renderList(yours, theirs, file.type, field, file.id, resolution);
-                       }
-                       else if (typeof yours === 'object') {
-                               return this.renderObjects(yours, theirs, file.type, field, file.id, resolution);
-                       }
-               } else if (theirs) {
-                       if (Array.isArray(theirs)) {
-                               return this.renderList(yours, theirs, file.type, field, file.id, resolution);
-                       }
-                       else if (typeof theirs === 'object') {
-                               return this.renderObjects(yours, theirs, file.type, field, file.id, resolution);
-                       }
-               }
-               let {conflictsOnly} = this.state;
-               return (<TextCompare key={'text_' + file.id + '_' + field} resolution={resolution}
-                        field={field} type={file.type} yours={yours} theirs={theirs} conflictsOnly={conflictsOnly} />);
-       }
+    renderField(field, file, yours, theirs, resolution) {
+        if (yours) {
+            if (Array.isArray(yours)) {
+                return this.renderList(
+                    yours,
+                    theirs,
+                    file.type,
+                    field,
+                    file.id,
+                    resolution
+                );
+            } else if (typeof yours === 'object') {
+                return this.renderObjects(
+                    yours,
+                    theirs,
+                    file.type,
+                    field,
+                    file.id,
+                    resolution
+                );
+            }
+        } else if (theirs) {
+            if (Array.isArray(theirs)) {
+                return this.renderList(
+                    yours,
+                    theirs,
+                    file.type,
+                    field,
+                    file.id,
+                    resolution
+                );
+            } else if (typeof theirs === 'object') {
+                return this.renderObjects(
+                    yours,
+                    theirs,
+                    file.type,
+                    field,
+                    file.id,
+                    resolution
+                );
+            }
+        }
+        let { conflictsOnly } = this.state;
+        return (
+            <TextCompare
+                key={'text_' + file.id + '_' + field}
+                resolution={resolution}
+                field={field}
+                type={file.type}
+                yours={yours}
+                theirs={theirs}
+                conflictsOnly={conflictsOnly}
+            />
+        );
+    }
 
-       getUnion(yours = {},theirs = {}) {
-               let yoursKeys = Object.keys(yours);
-               let theirsKeys = Object.keys(theirs);
-               let myUn = union(yoursKeys, theirsKeys);
-               return myUn;//.sort((a, b) => a > b);
-       }
+    getUnion(yours = {}, theirs = {}) {
+        let yoursKeys = Object.keys(yours);
+        let theirsKeys = Object.keys(theirs);
+        let myUn = union(yoursKeys, theirsKeys);
+        return myUn; //.sort((a, b) => a > b);
+    }
 
-       updateCollapseState(conflictId) {
-               const {fetchConflict, item: {id: itemId, version}, /*conflicts*/} = this.props;
-               let isCollapsed = this.state.collapsingSections[conflictId];
-               // if (!isCollapsed && !(conflicts && conflictId in conflicts)) {
-               if (!isCollapsed) {
-                       fetchConflict({cid: conflictId, itemId, version});
-               }
-               this.setState({
-                       collapsingSections: {
-                               ...this.state.collapsingSections,
-                               [conflictId]: !isCollapsed
-                       }
-               });
-       }
+    updateCollapseState(conflictId) {
+        const {
+            fetchConflict,
+            item: { id: itemId, version } /*conflicts*/
+        } = this.props;
+        let isCollapsed = this.state.collapsingSections[conflictId];
+        // if (!isCollapsed && !(conflicts && conflictId in conflicts)) {
+        if (!isCollapsed) {
+            fetchConflict({ cid: conflictId, itemId, version });
+        }
+        this.setState({
+            collapsingSections: {
+                ...this.state.collapsingSections,
+                [conflictId]: !isCollapsed
+            }
+        });
+    }
 }
 
 export default MergeEditorView;
index b17536f..5b28c5d 100644 (file)
@@ -32,40 +32,40 @@ import Revisions from 'sdc-app/onboarding/revisions/Revisions.js';
 import VendorSelector from 'sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx';
 
 export const modalContentMapper = {
-       SOFTWARE_PRODUCT_CREATION: 'SOFTWARE_PRODUCT_CREATION',
-       LICENSE_MODEL_CREATION: 'LICENSE_MODEL_CREATION',
-       SUMBIT_ERROR_RESPONSE: 'SUMBIT_ERROR_RESPONSE',
-       COMPONENT_COMPUTE_FLAVOR_EDITOR: 'COMPONENT_COMPUTE_FLAVOR_EDITOR',
-       NIC_EDITOR: 'NIC_EDITOR',
-       NIC_CREATION: 'NIC_CREATION',
-       COMPONENT_CREATION: 'COMPONENT_CREATION',
-       SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR : 'SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR',
-       DEPLOYMENT_FLAVOR_EDITOR: 'DEPLOYMENT_FLAVOR_EDITOR',
-       MANAGE_PERMISSIONS: 'MANAGE_PERMISSIONS',
-       VERSION_CREATION: 'VERSION_CREATION',
-       COMMIT_COMMENT: 'COMMIT_COMMENT',
-       VERSION_TREE: 'VERSION_TREE',
-       MERGE_EDITOR: 'MERGE_EDITOR',
-       REVISIONS_LIST: 'REVISIONS_LIST',
-       VENDOR_SELECTOR: 'VENDOR_SELECTOR'
-
+    SOFTWARE_PRODUCT_CREATION: 'SOFTWARE_PRODUCT_CREATION',
+    LICENSE_MODEL_CREATION: 'LICENSE_MODEL_CREATION',
+    SUMBIT_ERROR_RESPONSE: 'SUMBIT_ERROR_RESPONSE',
+    COMPONENT_COMPUTE_FLAVOR_EDITOR: 'COMPONENT_COMPUTE_FLAVOR_EDITOR',
+    NIC_EDITOR: 'NIC_EDITOR',
+    NIC_CREATION: 'NIC_CREATION',
+    COMPONENT_CREATION: 'COMPONENT_CREATION',
+    SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR:
+        'SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR',
+    DEPLOYMENT_FLAVOR_EDITOR: 'DEPLOYMENT_FLAVOR_EDITOR',
+    MANAGE_PERMISSIONS: 'MANAGE_PERMISSIONS',
+    VERSION_CREATION: 'VERSION_CREATION',
+    COMMIT_COMMENT: 'COMMIT_COMMENT',
+    VERSION_TREE: 'VERSION_TREE',
+    MERGE_EDITOR: 'MERGE_EDITOR',
+    REVISIONS_LIST: 'REVISIONS_LIST',
+    VENDOR_SELECTOR: 'VENDOR_SELECTOR'
 };
 
 export const modalContentComponents = {
-       SUMBIT_ERROR_RESPONSE: SubmitErrorResponse,
-       SOFTWARE_PRODUCT_CREATION: SoftwareProductCreation,
-       VERSION_CREATION: VersionPageCreation,
-       LICENSE_MODEL_CREATION: LicenseModelCreation,
-       COMPONENT_COMPUTE_FLAVOR_EDITOR: ComputeFlavorEditor,
-       NIC_EDITOR: SoftwareProductComponentsNICEditor,
-       NIC_CREATION: NICCreation,
-       COMPONENT_CREATION: ComponentCreation,
-       SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR : SoftwareProductComponentImageEditor,
-       DEPLOYMENT_FLAVOR_EDITOR: SoftwareProductDeploymentEditor,
-       MANAGE_PERMISSIONS: PermissionsManager,
-       COMMIT_COMMENT: CommitCommentModal,
-       VERSION_TREE: Tree,
-       MERGE_EDITOR: MergeEditor,
-       REVISIONS_LIST: Revisions,
-       VENDOR_SELECTOR: VendorSelector
+    SUMBIT_ERROR_RESPONSE: SubmitErrorResponse,
+    SOFTWARE_PRODUCT_CREATION: SoftwareProductCreation,
+    VERSION_CREATION: VersionPageCreation,
+    LICENSE_MODEL_CREATION: LicenseModelCreation,
+    COMPONENT_COMPUTE_FLAVOR_EDITOR: ComputeFlavorEditor,
+    NIC_EDITOR: SoftwareProductComponentsNICEditor,
+    NIC_CREATION: NICCreation,
+    COMPONENT_CREATION: ComponentCreation,
+    SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR: SoftwareProductComponentImageEditor,
+    DEPLOYMENT_FLAVOR_EDITOR: SoftwareProductDeploymentEditor,
+    MANAGE_PERMISSIONS: PermissionsManager,
+    COMMIT_COMMENT: CommitCommentModal,
+    VERSION_TREE: Tree,
+    MERGE_EDITOR: MergeEditor,
+    REVISIONS_LIST: Revisions,
+    VENDOR_SELECTOR: VendorSelector
 };
index 916f724..6ac6d75 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './JSONSchemaReducerConstants.js';
+import { actionTypes } from './JSONSchemaReducerConstants.js';
 import Validator from 'nfvo-utils/Validator.js';
 import JSONSchema from 'nfvo-utils/json/JSONSchema.js';
 import JSONPointer from 'nfvo-utils/json/JSONPointer.js';
 import forOwn from 'lodash/forOwn.js';
 import isArray from 'lodash/isArray.js';
 
-
 function flattenData(data, result, pointer = '') {
-       let newPointer = pointer;
-       if (typeof data === 'object' && !isArray(data)) {
-               for (let i in data) {
-                       newPointer = newPointer ? newPointer + '/' + i : i;
-                       flattenData(data[i], result, newPointer);
-                       newPointer = pointer;
-               }
-       } else {
-               result[newPointer] = data;
-       }
+    let newPointer = pointer;
+    if (typeof data === 'object' && !isArray(data)) {
+        for (let i in data) {
+            newPointer = newPointer ? newPointer + '/' + i : i;
+            flattenData(data[i], result, newPointer);
+            newPointer = pointer;
+        }
+    } else {
+        result[newPointer] = data;
+    }
 }
 
-function updateSchemaDataAndValidateReducer (state = {}, action, questionnaireName) {
-       let genericFieldInfoClone;
-       switch (action.type) {
-               case actionTypes.DATA_LOADED:
-                       if (questionnaireName !== action.qName) {return {...state};}
-                       const schema = action.payload.qschema;
-                       let schemaLoader = new JSONSchema();
-                       schemaLoader.setSchema(schema);
-                       schemaLoader.setSupportedValidationFunctions(Object.keys(Validator.globalValidationFunctions));
-                       let {genericFieldInfo} = schemaLoader.flattenSchema();
-
-                       let data = action.payload.qdata;
-                       let dataMap =  {};
-                       flattenData(data, dataMap);
-
-                       return {
-                               ...state,
-                               qdata: action.payload.qdata, // the original hierarchical data. to be used for submit and save
-                               qgenericFieldInfo : genericFieldInfo, // information about the fields that the view will require and reducer will need, such as validations, enum to use, etc.
-                               dataMap //  flattened schema data for ease of use
-                       };
-
-               case actionTypes.DATA_CHANGED:
-                       let changedData = action.deltaData;
-                       if (questionnaireName !== action.qName)  {return {...state};}
-
-                       genericFieldInfoClone = {...state.qgenericFieldInfo};
-                       let qDataClone = {...state.qdata};
-                       let dataMapClone = {...state.dataMap};
-
-                       forOwn(changedData,(value, key) => {
-                               if (state.qgenericFieldInfo[key]) {
-                                       let result = Validator.validate(key, value, state.qgenericFieldInfo[key].validations, state, action.customValidations);
-                                       genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
-                                       qDataClone = JSONPointer.setValue(state.qdata, '/' + key, value);
-                                       dataMapClone[key] = value;
-                               }
-                       });
-
-                       return {
-                               ...state,
-                               qdata: qDataClone,
-                               dataMap: dataMapClone,
-                               qgenericFieldInfo: genericFieldInfoClone
-                       };
-
-               case actionTypes.VALIDATE_DATA:
-                       let specificFields = action.data;
-                       if (questionnaireName !== action.qName)  {return {...state};}
-                       genericFieldInfoClone = {...state.qgenericFieldInfo};
-                       forOwn(specificFields,(value, key) => {
-                               let result = Validator.validate(key, value, state.qgenericFieldInfo[key].validations, state, action.customValidations);
-                               genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
-                       });
-                       return {
-                               ...state,
-                               formReady: null,
-                               qgenericFieldInfo: genericFieldInfoClone
-                       };
-
-               case actionTypes.VALIDATE_FORM:
-                       if (questionnaireName !== action.qName)  {return {...state};}
-                       genericFieldInfoClone = {...state.qgenericFieldInfo};
-                       let formReady = true;
-                       forOwn(state.qgenericFieldInfo,(value, key) => {
-                               let val = state.dataMap[key] ? state.dataMap[key] : '';
-                               let result = Validator.validate(key, val, state.qgenericFieldInfo[key].validations, state, action.customValidations);
-                               genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
-                               if (!result.isValid) {
-                                       formReady = false;
-                               }
-                       });
-                       return {
-                               ...state,
-                               formReady,
-                               qgenericFieldInfo: genericFieldInfoClone
-                       };
-
-               default:
-                       return state;
-       }
-};
+function updateSchemaDataAndValidateReducer(
+    state = {},
+    action,
+    questionnaireName
+) {
+    let genericFieldInfoClone;
+    switch (action.type) {
+        case actionTypes.DATA_LOADED:
+            if (questionnaireName !== action.qName) {
+                return { ...state };
+            }
+            const schema = action.payload.qschema;
+            let schemaLoader = new JSONSchema();
+            schemaLoader.setSchema(schema);
+            schemaLoader.setSupportedValidationFunctions(
+                Object.keys(Validator.globalValidationFunctions)
+            );
+            let { genericFieldInfo } = schemaLoader.flattenSchema();
+
+            let data = action.payload.qdata;
+            let dataMap = {};
+            flattenData(data, dataMap);
+
+            return {
+                ...state,
+                qdata: action.payload.qdata, // the original hierarchical data. to be used for submit and save
+                qgenericFieldInfo: genericFieldInfo, // information about the fields that the view will require and reducer will need, such as validations, enum to use, etc.
+                dataMap //  flattened schema data for ease of use
+            };
+
+        case actionTypes.DATA_CHANGED:
+            let changedData = action.deltaData;
+            if (questionnaireName !== action.qName) {
+                return { ...state };
+            }
+
+            genericFieldInfoClone = { ...state.qgenericFieldInfo };
+            let qDataClone = { ...state.qdata };
+            let dataMapClone = { ...state.dataMap };
+
+            forOwn(changedData, (value, key) => {
+                if (state.qgenericFieldInfo[key]) {
+                    let result = Validator.validate(
+                        key,
+                        value,
+                        state.qgenericFieldInfo[key].validations,
+                        state,
+                        action.customValidations
+                    );
+                    genericFieldInfoClone[key] = {
+                        ...genericFieldInfoClone[key],
+                        isValid: result.isValid,
+                        errorText: result.errorText
+                    };
+                    qDataClone = JSONPointer.setValue(
+                        state.qdata,
+                        '/' + key,
+                        value
+                    );
+                    dataMapClone[key] = value;
+                }
+            });
+
+            return {
+                ...state,
+                qdata: qDataClone,
+                dataMap: dataMapClone,
+                qgenericFieldInfo: genericFieldInfoClone
+            };
+
+        case actionTypes.VALIDATE_DATA:
+            let specificFields = action.data;
+            if (questionnaireName !== action.qName) {
+                return { ...state };
+            }
+            genericFieldInfoClone = { ...state.qgenericFieldInfo };
+            forOwn(specificFields, (value, key) => {
+                let result = Validator.validate(
+                    key,
+                    value,
+                    state.qgenericFieldInfo[key].validations,
+                    state,
+                    action.customValidations
+                );
+                genericFieldInfoClone[key] = {
+                    ...genericFieldInfoClone[key],
+                    isValid: result.isValid,
+                    errorText: result.errorText
+                };
+            });
+            return {
+                ...state,
+                formReady: null,
+                qgenericFieldInfo: genericFieldInfoClone
+            };
+
+        case actionTypes.VALIDATE_FORM:
+            if (questionnaireName !== action.qName) {
+                return { ...state };
+            }
+            genericFieldInfoClone = { ...state.qgenericFieldInfo };
+            let formReady = true;
+            forOwn(state.qgenericFieldInfo, (value, key) => {
+                let val = state.dataMap[key] ? state.dataMap[key] : '';
+                let result = Validator.validate(
+                    key,
+                    val,
+                    state.qgenericFieldInfo[key].validations,
+                    state,
+                    action.customValidations
+                );
+                genericFieldInfoClone[key] = {
+                    ...genericFieldInfoClone[key],
+                    isValid: result.isValid,
+                    errorText: result.errorText
+                };
+                if (!result.isValid) {
+                    formReady = false;
+                }
+            });
+            return {
+                ...state,
+                formReady,
+                qgenericFieldInfo: genericFieldInfoClone
+            };
+
+        default:
+            return state;
+    }
+}
 
 export function createJSONSchemaReducer(questionnaireName) {
-       return (state = {}, action) => {
-               return updateSchemaDataAndValidateReducer(state, action, questionnaireName);
-       };
-};
-
-export function createComposedJSONSchemaReducer(questionnaireName, additionalActionsReducer) {
-       return (state = {}, action) => {
-               if(action.type === actionTypes.VALIDATE_DATA ||
-                       action.type === actionTypes.VALIDATE_FORM ||
-                       action.type === actionTypes.DATA_CHANGED ||
-                       action.type === actionTypes.DATA_LOADED
-               ) {
-                       return updateSchemaDataAndValidateReducer(state, action, questionnaireName);
-               } else {
-                       return additionalActionsReducer(state, action);
-               }
-       };
-};
-
-
-
-
-
-
+    return (state = {}, action) => {
+        return updateSchemaDataAndValidateReducer(
+            state,
+            action,
+            questionnaireName
+        );
+    };
+}
 
+export function createComposedJSONSchemaReducer(
+    questionnaireName,
+    additionalActionsReducer
+) {
+    return (state = {}, action) => {
+        if (
+            action.type === actionTypes.VALIDATE_DATA ||
+            action.type === actionTypes.VALIDATE_FORM ||
+            action.type === actionTypes.DATA_CHANGED ||
+            action.type === actionTypes.DATA_LOADED
+        ) {
+            return updateSchemaDataAndValidateReducer(
+                state,
+                action,
+                questionnaireName
+            );
+        } else {
+            return additionalActionsReducer(state, action);
+        }
+    };
+}
index 6007b87..439613d 100644 (file)
@@ -16,8 +16,8 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       DATA_LOADED: null,
-       DATA_CHANGED: null,
-       VALIDATE_FORM: null,
-       VALIDATE_DATA: null
+    DATA_LOADED: null,
+    DATA_CHANGED: null,
+    VALIDATE_FORM: null,
+    VALIDATE_DATA: null
 });
index 49f1e3d..3049770 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './PlainDataReducerConstants.js';
+import { actionTypes } from './PlainDataReducerConstants.js';
 import Validator from 'nfvo-utils/Validator.js';
 import forOwn from 'lodash/forOwn.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
 function updateDataAndValidateReducer(state = {}, action) {
-       let genericFieldInfoCopy;
-       switch (action.type) {
-               case actionTypes.DATA_CHANGED:
-                       let changed = action.deltaData;
-                       if (!action.formName || (state.formName !== action.formName)) {return {...state};}
-                       genericFieldInfoCopy = {...state.genericFieldInfo};
-                       forOwn(changed,(value, key) => {
-                               if (state.genericFieldInfo[key]) {
-                                       let result = Validator.validate(key, value, state.genericFieldInfo[key].validations, state, action.customValidations);
-                                       genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
-                               }
-                       });
-                       return {
-                               ...state,
-                               formReady: null,
-                               data: {
-                                       ...state.data,
-                                       ...action.deltaData
-                               },
-                               genericFieldInfo: genericFieldInfoCopy
-                       };
-               case actionTypes.VALIDATE_FORM:
-                       if (!action.formName || (state.formName !== action.formName)) {return {...state};}
-                       genericFieldInfoCopy = {...state.genericFieldInfo};
-                       let formReady = true;
-                       forOwn(state.genericFieldInfo,(value, key) => {
-                               let val = state.data && state.data[key] ? state.data[key] : '';
-                               let result = Validator.validate(key, val, state.genericFieldInfo[key].validations, state, {});
-                               if(val.choice !== undefined) {
-                                       result = Validator.validate(key, val.choice, state.genericFieldInfo[key].validations, state, {});
-                               }
-                               if(val.choice !== undefined && val.choice === optionInputOther.OTHER) {
-                                       result = Validator.validate(key, val.other, state.genericFieldInfo[key].validations, state, {});
-                               }
-                               genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
-                               if (!result.isValid) {
-                                       formReady = false;
-                               }
-                       });
-                       return {
-                               ...state,
-                               formReady,
-                               genericFieldInfo: genericFieldInfoCopy
-                       };
-               case actionTypes.VALIDATE_DATA:
-                       let specificFields = action.data;
-                       if (!action.formName || (state.formName !== action.formName)) {return {...state};}
-                       genericFieldInfoCopy = {...state.genericFieldInfo};
-                       forOwn(specificFields,(value, key) => {
-                               let result = Validator.validate(key, value, state.genericFieldInfo[key].validations, state, action.customValidations);
-                               genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
-                       });
-                       return {
-                               ...state,
-                               formReady: null,
-                               genericFieldInfo: genericFieldInfoCopy
-                       };
-               default:
-                       return state;
-       }
-};
+    let genericFieldInfoCopy;
+    switch (action.type) {
+        case actionTypes.DATA_CHANGED:
+            let changed = action.deltaData;
+            if (!action.formName || state.formName !== action.formName) {
+                return { ...state };
+            }
+            genericFieldInfoCopy = { ...state.genericFieldInfo };
+            forOwn(changed, (value, key) => {
+                if (state.genericFieldInfo[key]) {
+                    let result = Validator.validate(
+                        key,
+                        value,
+                        state.genericFieldInfo[key].validations,
+                        state,
+                        action.customValidations
+                    );
+                    genericFieldInfoCopy[key] = {
+                        ...genericFieldInfoCopy[key],
+                        isValid: result.isValid,
+                        errorText: result.errorText
+                    };
+                }
+            });
+            return {
+                ...state,
+                formReady: null,
+                data: {
+                    ...state.data,
+                    ...action.deltaData
+                },
+                genericFieldInfo: genericFieldInfoCopy
+            };
+        case actionTypes.VALIDATE_FORM:
+            if (!action.formName || state.formName !== action.formName) {
+                return { ...state };
+            }
+            genericFieldInfoCopy = { ...state.genericFieldInfo };
+            let formReady = true;
+            forOwn(state.genericFieldInfo, (value, key) => {
+                let val = state.data && state.data[key] ? state.data[key] : '';
+                let result = Validator.validate(
+                    key,
+                    val,
+                    state.genericFieldInfo[key].validations,
+                    state,
+                    {}
+                );
+                if (val.choice !== undefined) {
+                    result = Validator.validate(
+                        key,
+                        val.choice,
+                        state.genericFieldInfo[key].validations,
+                        state,
+                        {}
+                    );
+                }
+                if (
+                    val.choice !== undefined &&
+                    val.choice === optionInputOther.OTHER
+                ) {
+                    result = Validator.validate(
+                        key,
+                        val.other,
+                        state.genericFieldInfo[key].validations,
+                        state,
+                        {}
+                    );
+                }
+                genericFieldInfoCopy[key] = {
+                    ...genericFieldInfoCopy[key],
+                    isValid: result.isValid,
+                    errorText: result.errorText
+                };
+                if (!result.isValid) {
+                    formReady = false;
+                }
+            });
+            return {
+                ...state,
+                formReady,
+                genericFieldInfo: genericFieldInfoCopy
+            };
+        case actionTypes.VALIDATE_DATA:
+            let specificFields = action.data;
+            if (!action.formName || state.formName !== action.formName) {
+                return { ...state };
+            }
+            genericFieldInfoCopy = { ...state.genericFieldInfo };
+            forOwn(specificFields, (value, key) => {
+                let result = Validator.validate(
+                    key,
+                    value,
+                    state.genericFieldInfo[key].validations,
+                    state,
+                    action.customValidations
+                );
+                genericFieldInfoCopy[key] = {
+                    ...genericFieldInfoCopy[key],
+                    isValid: result.isValid,
+                    errorText: result.errorText
+                };
+            });
+            return {
+                ...state,
+                formReady: null,
+                genericFieldInfo: genericFieldInfoCopy
+            };
+        default:
+            return state;
+    }
+}
 
 export function createPlainDataReducer(loadReducer) {
-       return (state = {}, action) => {
-               if(action.type === actionTypes.VALIDATE_DATA ||
-                       action.type === actionTypes.VALIDATE_FORM ||
-                       action.type === actionTypes.DATA_CHANGED
-               ) {
-                       return updateDataAndValidateReducer(state, action);
-               } else {
-                       return loadReducer(state, action);
-               }
-       };
-};
-
-
-
-
-
-
+    return (state = {}, action) => {
+        if (
+            action.type === actionTypes.VALIDATE_DATA ||
+            action.type === actionTypes.VALIDATE_FORM ||
+            action.type === actionTypes.DATA_CHANGED
+        ) {
+            return updateDataAndValidateReducer(state, action);
+        } else {
+            return loadReducer(state, action);
+        }
+    };
+}
index 135361d..8c38483 100644 (file)
@@ -16,7 +16,7 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       DATA_CHANGED: null,
-       VALIDATE_FORM: null,
-       VALIDATE_DATA: null
+    DATA_CHANGED: null,
+    VALIDATE_FORM: null,
+    VALIDATE_DATA: null
 });
index 8444e3f..b450d47 100644 (file)
 import configData from './config.json';
 
 class Configuration {
+    get(key) {
+        return configData[key];
+    }
 
-       get(key) {
-               return configData[key];
-       }
+    set(key, value) {
+        var prev = configData[key];
+        configData[key] = value;
+        return prev;
+    }
 
-       set(key, value) {
-               var prev = configData[key];
-               configData[key] = value;
-               return prev;
-       }
+    setCatalogApiRoot(CatalogApiRoot) {
+        let restCatalogPrefix = CatalogApiRoot,
+            restPrefix = CatalogApiRoot.replace(
+                /\/feProxy\b[^:]*$/,
+                '/feProxy/onboarding-api'
+            );
 
-       setCatalogApiRoot(CatalogApiRoot) {
-               let restCatalogPrefix = CatalogApiRoot,
-                       restPrefix = CatalogApiRoot.replace(/\/feProxy\b[^:]*$/, '/feProxy/onboarding-api');
+        this.set('restPrefix', restPrefix);
+        this.set('restCatalogPrefix', restCatalogPrefix);
+    }
 
-               this.set('restPrefix', restPrefix);
-               this.set('restCatalogPrefix', restCatalogPrefix);
-       }
+    setCatalogApiHeaders(CatalogApiHeaders) {
+        this.set('CatalogApiHeaders', CatalogApiHeaders);
 
-       setCatalogApiHeaders(CatalogApiHeaders) {
-               this.set('CatalogApiHeaders', CatalogApiHeaders);
-
-               let {userId: {value: UserID} = {}} = CatalogApiHeaders;
-               this.set('UserID', UserID);
-       }
+        let { userId: { value: UserID } = {} } = CatalogApiHeaders;
+        this.set('UserID', UserID);
+    }
 }
 
 const configuration = new Configuration();
 
 (function setDefaultRestPrefixes(configuration) {
-       configuration.set('restPrefix', configuration.get('defaultRestPrefix'));
-       configuration.set('restCatalogPrefix', configuration.get('defaultRestCatalogPrefix'));
-       configuration.set('appContextPath', configuration.get('appContextPath'));
+    configuration.set('restPrefix', configuration.get('defaultRestPrefix'));
+    configuration.set(
+        'restCatalogPrefix',
+        configuration.get('defaultRestCatalogPrefix')
+    );
+    configuration.set('appContextPath', configuration.get('appContextPath'));
 })(configuration);
 (function setDefaultWebsocketConfig(configuration) {
-       let websocketPort = configuration.get('defaultWebsocketPort');
-       if (DEBUG) {
-               websocketPort = configuration.get('defaultDebugWebsocketPort');
-       }
-       configuration.set('websocketPort', websocketPort);
-       configuration.set('websocketPath', configuration.get('defaultWebsocketPath'));
+    let websocketPort = configuration.get('defaultWebsocketPort');
+    if (DEBUG) {
+        websocketPort = configuration.get('defaultDebugWebsocketPort');
+    }
+    configuration.set('websocketPort', websocketPort);
+    configuration.set(
+        'websocketPath',
+        configuration.get('defaultWebsocketPath')
+    );
 })(configuration);
 
 export default configuration;
index 5bb911d..5ab5480 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './FeaturesConstants.js';
-
+import { actionTypes } from './FeaturesConstants.js';
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/togglz`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/togglz`;
 }
 
 function fetchList() {
-       return RestAPIUtil.fetch(baseUrl());
+    return RestAPIUtil.fetch(baseUrl());
 }
 
 export default {
-       getFeaturesList(dispatch) {
-               return fetchList().then(response => {
-                       dispatch({
-                               type: actionTypes.FEATURES_LIST_LOADED,
-                               features: response.features
-                       });
-               }).catch(() => console.error('An exception occured while trying to fetch the toggleZ features.') );
-       }
+    getFeaturesList(dispatch) {
+        return fetchList()
+            .then(response => {
+                dispatch({
+                    type: actionTypes.FEATURES_LIST_LOADED,
+                    features: response.features
+                });
+            })
+            .catch(() =>
+                console.error(
+                    'An exception occured while trying to fetch the toggleZ features.'
+                )
+            );
+    }
 };
-
index f962d24..314e86a 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       FEATURES_LIST_LOADED: null
+    FEATURES_LIST_LOADED: null
 });
 
 export const featureToggleNames = {
-       ARCHIVE_ITEM: 'ARCHIVE_ITEM',
-       FILTER: 'FILTER'
-};
\ No newline at end of file
+    ARCHIVE_ITEM: 'ARCHIVE_ITEM',
+    FILTER: 'FILTER'
+};
index d7c8624..064afe9 100644 (file)
  * permissions and limitations under the License.
  */
 
- import {actionTypes} from './FeaturesConstants.js';
+import { actionTypes } from './FeaturesConstants.js';
 
- export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FEATURES_LIST_LOADED:
-                       return [...action.features];
-               default:
-                       return state;
-       }            
- };
\ No newline at end of file
+export default (state = [], action) => {
+    switch (action.type) {
+        case actionTypes.FEATURES_LIST_LOADED:
+            return [...action.features];
+        default:
+            return state;
+    }
+};
index 5e0df14..d33c76e 100644 (file)
  * permissions and limitations under the License.
  */
 
-
- /**
+/**
  * Feature toggling decorator
- *     usage: 
- * 
+ *     usage:
+ *
  * @featureToggle('FeatureName')
  * class Example extends React.Component {
  *             render() {
  *                     return (<div>test feature</div>);
  *             }
  * }
- * 
- *  OR 
- * 
+ *
+ *  OR
+ *
  * const TestFeature = () => (<div>test feature</div>)
  * export default featureToggle('FeatureName')(TestFeature)
- * 
+ *
  */
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
+
+export const FeatureComponent = props => {
+    const { features = [], featureName, InnerComponent, ...otherProps } = props;
+    const AComp = InnerComponent.AComp ? InnerComponent.AComp : InnerComponent;
 
-export const FeatureComponent = (props) => {
-       const {features = [], featureName, InnerComponent, ...otherProps} = props;
-       const AComp = InnerComponent.AComp ? InnerComponent.AComp : InnerComponent;
-       
-       return !!features.find(el => el.name === featureName && el.active) ?
-                <AComp {...otherProps}/> 
-                : InnerComponent.BComp ? <InnerComponent.BComp {...otherProps}/> : null;
+    return !!features.find(el => el.name === featureName && el.active) ? (
+        <AComp {...otherProps} />
+    ) : InnerComponent.BComp ? (
+        <InnerComponent.BComp {...otherProps} />
+    ) : null;
 };
 
 FeatureComponent.propTypes = {
-       features: PropTypes.array,
-       featureName: PropTypes.string.isRequired
+    features: PropTypes.array,
+    featureName: PropTypes.string.isRequired
 };
 
-
 export default function featureToggle(featureName) {
-       return (InnerComponent) => {            
-               return connect(({features}) => {return {features, featureName, InnerComponent};})(FeatureComponent);
-       };
+    return InnerComponent => {
+        return connect(({ features }) => {
+            return { features, featureName, InnerComponent };
+        })(FeatureComponent);
+    };
 }
-
index c90521d..505dace 100644 (file)
@@ -16,9 +16,9 @@
 
 import store from 'sdc-app/AppStore.js';
 
-
-export default ({featureName, restFunction, mockResult}) => {
-       const {features} = store.getState();
-       return !!features.find(el => el.name === featureName && el.active) ? 
-               restFunction() : Promise.resolve(mockResult);
-};
\ No newline at end of file
+export default ({ featureName, restFunction, mockResult }) => {
+    const { features } = store.getState();
+    return !!features.find(el => el.name === featureName && el.active)
+        ? restFunction()
+        : Promise.resolve(mockResult);
+};
index 61a419b..9fb65f3 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes, enums} from './FlowsConstants.js';
+import { actionTypes, enums } from './FlowsConstants.js';
 import SequenceDiagramModelHelper from './SequenceDiagramModelHelper.js';
 
-
 function baseUrl(serviceId, artifactId = '') {
-       const restCatalogPrefix = Configuration.get('restCatalogPrefix');
-       return `${restCatalogPrefix}/v1/catalog/services/${serviceId}/artifacts/${artifactId}`;
+    const restCatalogPrefix = Configuration.get('restCatalogPrefix');
+    return `${restCatalogPrefix}/v1/catalog/services/${serviceId}/artifacts/${artifactId}`;
 }
 
 function encodeDataToBase64(dataAsString) {
-       return window.btoa(dataAsString);
+    return window.btoa(dataAsString);
 }
 
 function decodeDataToBase64(encodedData) {
-       return window.atob(encodedData);
+    return window.atob(encodedData);
 }
 
 function encodeContent(flowData) {
-       let data = {
-               VERSION: {
-                       major: 1,
-                       minor: 0
-               },
-               description: flowData.description,
-               sequenceDiagramModel: flowData.sequenceDiagramModel
-       };
-
-       return encodeDataToBase64(JSON.stringify(data));
+    let data = {
+        VERSION: {
+            major: 1,
+            minor: 0
+        },
+        description: flowData.description,
+        sequenceDiagramModel: flowData.sequenceDiagramModel
+    };
+
+    return encodeDataToBase64(JSON.stringify(data));
 }
 
 function decodeContent(base64Contents) {
-       let description, sequenceDiagramModel;
-       let payload = JSON.parse(decodeDataToBase64(base64Contents));
-
-       if (payload.VERSION === undefined) {
-               description = payload.description || 'Please, provide description...';
-               sequenceDiagramModel = payload.data || payload;
-               sequenceDiagramModel = sequenceDiagramModel.model || sequenceDiagramModel;
-
-       }
-       else if (payload.VERSION.major === 1) {
-               description = payload.description;
-               sequenceDiagramModel = payload.sequenceDiagramModel;
-       }
-
-       return {
-               description,
-               sequenceDiagramModel
-       };
+    let description, sequenceDiagramModel;
+    let payload = JSON.parse(decodeDataToBase64(base64Contents));
+
+    if (payload.VERSION === undefined) {
+        description = payload.description || 'Please, provide description...';
+        sequenceDiagramModel = payload.data || payload;
+        sequenceDiagramModel =
+            sequenceDiagramModel.model || sequenceDiagramModel;
+    } else if (payload.VERSION.major === 1) {
+        description = payload.description;
+        sequenceDiagramModel = payload.sequenceDiagramModel;
+    }
+
+    return {
+        description,
+        sequenceDiagramModel
+    };
 }
 
 function createOrUpdate(flowData) {
-       let createOrUpdateRequest = {
-               payloadData: encodeContent(flowData),
-               artifactLabel: flowData.artifactLabel || flowData.artifactName,
-               artifactName: flowData.artifactName,
-               artifactType: flowData.artifactType,
-               artifactGroupType: enums.INFORMATIONAL,
-               description: flowData.description
-       };
-
-       return RestAPIUtil.post(
-               baseUrl(flowData.serviceID, flowData.uniqueId),
-               createOrUpdateRequest,
-               {md5: true}
-       );
+    let createOrUpdateRequest = {
+        payloadData: encodeContent(flowData),
+        artifactLabel: flowData.artifactLabel || flowData.artifactName,
+        artifactName: flowData.artifactName,
+        artifactType: flowData.artifactType,
+        artifactGroupType: enums.INFORMATIONAL,
+        description: flowData.description
+    };
+
+    return RestAPIUtil.post(
+        baseUrl(flowData.serviceID, flowData.uniqueId),
+        createOrUpdateRequest,
+        { md5: true }
+    );
 }
 
 const FlowsActions = Object.freeze({
-
-       fetchFlowArtifacts(dispatch, {artifacts, diagramType, participants, serviceID, readonly}) {
-               let results = [];
-               if (!Object.keys(artifacts).length) {
-                       dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType, readonly});
-                       if (!readonly) {
-                               FlowsActions.openFlowDetailsEditor(dispatch);
-                       }
-               }
-               else {
-                       Object.keys(artifacts).forEach(artifact => results.push({
-                               artifactType: diagramType,
-                               participants,
-                               serviceID,
-                               ...artifacts[artifact]
-                       }));
-                       dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType, readonly});
-               }
-       },
-
-       fetchArtifact(dispatch, {flow}){
-               let {serviceID, uniqueId, participants} = flow;
-               return RestAPIUtil.fetch(baseUrl(serviceID, uniqueId)).then(response => {
-
-                       let {artifactName, base64Contents} = response;
-                       let {sequenceDiagramModel, ...other} = decodeContent(base64Contents);
-
-                       if (!sequenceDiagramModel) {
-                               sequenceDiagramModel = SequenceDiagramModelHelper.createModel({
-                                       id: uniqueId,
-                                       name: artifactName,
-                                       lifelines: participants
-                               });
-                       }
-                       else {
-                               sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(sequenceDiagramModel, {
-                                       name: artifactName,
-                                       lifelines: participants
-                               });
-                       }
-
-                       flow = {
-                               ...flow,
-                               ...other,
-                               uniqueId,
-                               artifactName,
-                               sequenceDiagramModel
-                       };
-
-                       dispatch({type: actionTypes.ARTIFACT_LOADED, flow});
-                       FlowsActions.openFlowDiagramEditor(dispatch, {flow});
-               });
-       },
-
-       createOrUpdateFlow(dispatch, {flow}, isNew) {
-               if (!isNew && flow.sequenceDiagramModel) {
-                       flow.sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(flow.sequenceDiagramModel, {
-                               name: flow.artifactName
-                       });
-               }
-               return createOrUpdate(flow).then(response => {
-                       let {uniqueId, artifactLabel} = response;
-                       flow = {...flow, uniqueId, artifactLabel};
-                       if (isNew) {
-                               flow.sequenceDiagramModel = SequenceDiagramModelHelper.createModel({id: uniqueId, name: flow.artifactName});
-                       }
-                       dispatch({type: actionTypes.ADD_OR_UPDATE_FLOW, flow});
-               });
-       },
-
-       deleteFlow(dispatch, {flow}) {
-               return RestAPIUtil.destroy(baseUrl(flow.serviceID, flow.uniqueId)).then(() => dispatch({
-                       type: actionTypes.DELETE_FLOW,
-                       flow
-               }));
-       },
-
-       openFlowDetailsEditor(dispatch, flow) {
-               dispatch({type: actionTypes.OPEN_FLOW_DETAILS_EDITOR, flow});
-       },
-
-       closeFlowDetailsEditor(dispatch) {
-               dispatch({type: actionTypes.CLOSE_FLOW_DETAILS_EDITOR});
-       },
-
-       openFlowDiagramEditor(dispatch, {flow}) {
-               dispatch({type: actionTypes.OPEN_FLOW_DIAGRAM_EDITOR, flow});
-       },
-
-       closeFlowDiagramEditor(dispatch) {
-               dispatch({type: actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR});
-       },
-
-       reset(dispatch) {
-               dispatch({type: actionTypes.RESET});
-       }
+    fetchFlowArtifacts(
+        dispatch,
+        { artifacts, diagramType, participants, serviceID, readonly }
+    ) {
+        let results = [];
+        if (!Object.keys(artifacts).length) {
+            dispatch({
+                type: actionTypes.FLOW_LIST_LOADED,
+                results,
+                participants,
+                serviceID,
+                diagramType,
+                readonly
+            });
+            if (!readonly) {
+                FlowsActions.openFlowDetailsEditor(dispatch);
+            }
+        } else {
+            Object.keys(artifacts).forEach(artifact =>
+                results.push({
+                    artifactType: diagramType,
+                    participants,
+                    serviceID,
+                    ...artifacts[artifact]
+                })
+            );
+            dispatch({
+                type: actionTypes.FLOW_LIST_LOADED,
+                results,
+                participants,
+                serviceID,
+                diagramType,
+                readonly
+            });
+        }
+    },
+
+    fetchArtifact(dispatch, { flow }) {
+        let { serviceID, uniqueId, participants } = flow;
+        return RestAPIUtil.fetch(baseUrl(serviceID, uniqueId)).then(
+            response => {
+                let { artifactName, base64Contents } = response;
+                let { sequenceDiagramModel, ...other } = decodeContent(
+                    base64Contents
+                );
+
+                if (!sequenceDiagramModel) {
+                    sequenceDiagramModel = SequenceDiagramModelHelper.createModel(
+                        {
+                            id: uniqueId,
+                            name: artifactName,
+                            lifelines: participants
+                        }
+                    );
+                } else {
+                    sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(
+                        sequenceDiagramModel,
+                        {
+                            name: artifactName,
+                            lifelines: participants
+                        }
+                    );
+                }
+
+                flow = {
+                    ...flow,
+                    ...other,
+                    uniqueId,
+                    artifactName,
+                    sequenceDiagramModel
+                };
+
+                dispatch({ type: actionTypes.ARTIFACT_LOADED, flow });
+                FlowsActions.openFlowDiagramEditor(dispatch, { flow });
+            }
+        );
+    },
+
+    createOrUpdateFlow(dispatch, { flow }, isNew) {
+        if (!isNew && flow.sequenceDiagramModel) {
+            flow.sequenceDiagramModel = SequenceDiagramModelHelper.updateModel(
+                flow.sequenceDiagramModel,
+                {
+                    name: flow.artifactName
+                }
+            );
+        }
+        return createOrUpdate(flow).then(response => {
+            let { uniqueId, artifactLabel } = response;
+            flow = { ...flow, uniqueId, artifactLabel };
+            if (isNew) {
+                flow.sequenceDiagramModel = SequenceDiagramModelHelper.createModel(
+                    {
+                        id: uniqueId,
+                        name: flow.artifactName
+                    }
+                );
+            }
+            dispatch({ type: actionTypes.ADD_OR_UPDATE_FLOW, flow });
+        });
+    },
+
+    deleteFlow(dispatch, { flow }) {
+        return RestAPIUtil.destroy(baseUrl(flow.serviceID, flow.uniqueId)).then(
+            () =>
+                dispatch({
+                    type: actionTypes.DELETE_FLOW,
+                    flow
+                })
+        );
+    },
+
+    openFlowDetailsEditor(dispatch, flow) {
+        dispatch({ type: actionTypes.OPEN_FLOW_DETAILS_EDITOR, flow });
+    },
+
+    closeFlowDetailsEditor(dispatch) {
+        dispatch({ type: actionTypes.CLOSE_FLOW_DETAILS_EDITOR });
+    },
+
+    openFlowDiagramEditor(dispatch, { flow }) {
+        dispatch({ type: actionTypes.OPEN_FLOW_DIAGRAM_EDITOR, flow });
+    },
+
+    closeFlowDiagramEditor(dispatch) {
+        dispatch({ type: actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR });
+    },
+
+    reset(dispatch) {
+        dispatch({ type: actionTypes.RESET });
+    }
 });
 
 export default FlowsActions;
index 2b3d86b..4dcd840 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
+    OPEN_FLOW_DETAILS_EDITOR: null,
+    CLOSE_FLOW_DETAILS_EDITOR: null,
 
-       OPEN_FLOW_DETAILS_EDITOR: null,
-       CLOSE_FLOW_DETAILS_EDITOR: null,
+    OPEN_FLOW_DIAGRAM_EDITOR: null,
+    CLOSE_FLOW_DIAGRAM_EDITOR: null,
 
-       OPEN_FLOW_DIAGRAM_EDITOR: null,
-       CLOSE_FLOW_DIAGRAM_EDITOR: null,
+    FLOW_LIST_LOADED: null,
+    ADD_OR_UPDATE_FLOW: null,
+    ARTIFACT_LOADED: null,
+    DELETE_FLOW: null,
 
-       FLOW_LIST_LOADED: null,
-       ADD_OR_UPDATE_FLOW: null,
-       ARTIFACT_LOADED: null,
-       DELETE_FLOW: null,
-
-       CURRENT_FLOW_DATA_CHANGED: null,
-
-       RESET: null
+    CURRENT_FLOW_DATA_CHANGED: null,
 
+    RESET: null
 });
 
 export const enums = {
-       WORKFLOW: 'WORKFLOW',
-       NETWORK: 'NETWORK_CALL_FLOW',
-       INFORMATIONAL: 'INFORMATIONAL',
-       INSTANTIATION_FLOWS: 'instantiationflows',
-       MESSAGE_FLOWS: 'messageflows'
+    WORKFLOW: 'WORKFLOW',
+    NETWORK: 'NETWORK_CALL_FLOW',
+    INFORMATIONAL: 'INFORMATIONAL',
+    INSTANTIATION_FLOWS: 'instantiationflows',
+    MESSAGE_FLOWS: 'messageflows'
 };
 
 export const FLOWS_EDITOR_FORM = 'FLOWS_FORM';
index f9585f9..b45a9fc 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import FlowsEditorModalView from './FlowsEditorModalView.jsx';
 import FlowsActions from './FlowsActions.js';
-import {FLOWS_EDITOR_FORM} from './FlowsConstants.js';
+import { FLOWS_EDITOR_FORM } from './FlowsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-export const mapStateToProps = ({flows}) => {
+export const mapStateToProps = ({ flows }) => {
+    let {
+        data = { artifactName: '', description: '' },
+        serviceID,
+        diagramType,
+        flowParticipants,
+        genericFieldInfo,
+        formReady
+    } = flows;
+    if (!data.serviceID) {
+        data.serviceID = serviceID;
+    }
+    if (!data.artifactType) {
+        data.artifactType = diagramType;
+    }
+    if (!data.participants) {
+        data.participants = flowParticipants;
+    }
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let {data = {artifactName: '', description: ''}, serviceID, diagramType, flowParticipants, genericFieldInfo, formReady} = flows;
-       if(!data.serviceID){
-               data.serviceID = serviceID;
-       }
-       if(!data.artifactType){
-               data.artifactType = diagramType;
-       }
-       if(!data.participants){
-               data.participants = flowParticipants;
-       }
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-
-       return {
-               currentFlow: data,
-               genericFieldInfo,
-               isFormValid,
-               formReady
-       };
+    return {
+        currentFlow: data,
+        genericFieldInfo,
+        isFormValid,
+        formReady
+    };
 };
 
-const mapActionsToProps = (dispatch, {isNewArtifact}) => {
-       return {
-               onSubmit: flow => {
-                       FlowsActions.closeFlowDetailsEditor(dispatch);
-                       FlowsActions.createOrUpdateFlow(dispatch, {flow}, isNewArtifact);
-               },
-               onCancel: () => FlowsActions.closeFlowDetailsEditor(dispatch),
-               onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: FLOWS_EDITOR_FORM}),
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, FLOWS_EDITOR_FORM)
-       };
+const mapActionsToProps = (dispatch, { isNewArtifact }) => {
+    return {
+        onSubmit: flow => {
+            FlowsActions.closeFlowDetailsEditor(dispatch);
+            FlowsActions.createOrUpdateFlow(dispatch, { flow }, isNewArtifact);
+        },
+        onCancel: () => FlowsActions.closeFlowDetailsEditor(dispatch),
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: FLOWS_EDITOR_FORM
+            }),
+        onValidateForm: () =>
+            ValidationHelper.validateForm(dispatch, FLOWS_EDITOR_FORM)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(FlowsEditorModalView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    FlowsEditorModalView
+);
index 1250a0b..8c805cc 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 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';
 
 class FlowsEditorModalView extends Component {
+    render() {
+        let {
+            onCancel,
+            onDataChanged,
+            currentFlow,
+            genericFieldInfo,
+            formReady,
+            isFormValid,
+            onValidateForm
+        } = this.props;
+        let { artifactName, description } = currentFlow;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        onSubmit={() => this.onSaveClicked()}
+                        onReset={onCancel}
+                        formReady={formReady}
+                        isValid={isFormValid}
+                        onValidateForm={() => onValidateForm()}>
+                        <Input
+                            type="text"
+                            name="name"
+                            label={i18n('Name')}
+                            isValid={genericFieldInfo['artifactName'].isValid}
+                            errorText={
+                                genericFieldInfo['artifactName'].errorText
+                            }
+                            isRequired={true}
+                            value={artifactName}
+                            onChange={artifactName =>
+                                onDataChanged({ artifactName })
+                            }
+                        />
+                        <Input
+                            type="textarea"
+                            name="description"
+                            label={i18n('Description')}
+                            isValid={genericFieldInfo['description'].isValid}
+                            errorText={
+                                genericFieldInfo['description'].errorText
+                            }
+                            isRequired={true}
+                            value={description}
+                            overlayPos="bottom"
+                            onChange={description =>
+                                onDataChanged({ description })
+                            }
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       render() {
-               let {onCancel, onDataChanged, currentFlow, genericFieldInfo, formReady, isFormValid, onValidateForm} = this.props;
-               let {artifactName, description} = currentFlow;
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       onSubmit={() => this.onSaveClicked()}
-                                       onReset={onCancel} formReady={formReady} isValid={isFormValid} onValidateForm={() => onValidateForm()} >
-                               <Input
-                                       type='text'
-                                       name='name'
-                                       label={i18n('Name')}
-                                       isValid={genericFieldInfo['artifactName'].isValid}
-                                       errorText={genericFieldInfo['artifactName'].errorText}
-                                       isRequired={true}
-                                       value={artifactName}
-                                       onChange={artifactName => onDataChanged({artifactName})}/>
-                               <Input
-                                       type='textarea'
-                                       name='description'
-                                       label={i18n('Description')}
-                                       isValid={genericFieldInfo['description'].isValid}
-                                       errorText={genericFieldInfo['description'].errorText}
-                                       isRequired={true}
-                                       value={description}
-                                       overlayPos='bottom'
-                                       onChange={description => onDataChanged({description})}/>
-                       </Form> }
-                       </div>
-               );
-       }
-
-       onSaveClicked() {
-               let {currentFlow, onSubmit} = this.props;
-               if (onSubmit) {
-                       onSubmit(currentFlow);
-               }
-       }
-
+    onSaveClicked() {
+        let { currentFlow, onSubmit } = this.props;
+        if (onSubmit) {
+            onSubmit(currentFlow);
+        }
+    }
 }
 
 export default FlowsEditorModalView;
index 642c578..2718c19 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import FlowsActions from './FlowsActions.js';
 import FlowsListEditorView from './FlowsListEditorView.jsx';
 
-export const mapStateToProps = ({flows}) => {
-       let {flowList = [], isDisplayModal, isModalInEditMode, shouldShowWorkflowsEditor = true, data = undefined, readonly} = flows;
-       let isCheckedOut = !readonly;
-       if(data && data.readonly){
-               isCheckedOut = !data.readonly;
-       }
+export const mapStateToProps = ({ flows }) => {
+    let {
+        flowList = [],
+        isDisplayModal,
+        isModalInEditMode,
+        shouldShowWorkflowsEditor = true,
+        data = undefined,
+        readonly
+    } = flows;
+    let isCheckedOut = !readonly;
+    if (data && data.readonly) {
+        isCheckedOut = !data.readonly;
+    }
 
-       return {
-               flowList,
-               isDisplayModal,
-               isCheckedOut,
-               isModalInEditMode,
-               shouldShowWorkflowsEditor,
-               currentFlow: data,
-               readonly
-       };
+    return {
+        flowList,
+        isDisplayModal,
+        isCheckedOut,
+        isModalInEditMode,
+        shouldShowWorkflowsEditor,
+        currentFlow: data,
+        readonly
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onAddWorkflowClick: () => FlowsActions.openFlowDetailsEditor(dispatch),
-               onEditFlowDetailsClick: flow => FlowsActions.openFlowDetailsEditor(dispatch, flow),
-               onEditFlowDiagramClick: flow => FlowsActions.fetchArtifact(dispatch, {flow}),
-               onDeleteFlowClick: flow => FlowsActions.deleteFlow(dispatch, {flow}),
-               onSequenceDiagramSaveClick: flow => {
-                       FlowsActions.closeFlowDiagramEditor(dispatch);
-                       FlowsActions.createOrUpdateFlow(dispatch, {flow});
-               },
-               onSequenceDiagramCloseClick: () => FlowsActions.closeFlowDiagramEditor(dispatch)
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onAddWorkflowClick: () => FlowsActions.openFlowDetailsEditor(dispatch),
+        onEditFlowDetailsClick: flow =>
+            FlowsActions.openFlowDetailsEditor(dispatch, flow),
+        onEditFlowDiagramClick: flow =>
+            FlowsActions.fetchArtifact(dispatch, { flow }),
+        onDeleteFlowClick: flow => FlowsActions.deleteFlow(dispatch, { flow }),
+        onSequenceDiagramSaveClick: flow => {
+            FlowsActions.closeFlowDiagramEditor(dispatch);
+            FlowsActions.createOrUpdateFlow(dispatch, { flow });
+        },
+        onSequenceDiagramCloseClick: () =>
+            FlowsActions.closeFlowDiagramEditor(dispatch)
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(FlowsListEditorView);
index 365b7f1..3b2ff06 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Modal from 'nfvo-components/modal/Modal.jsx';
@@ -25,125 +25,146 @@ import FlowsEditorModal from './FlowsEditorModal.js';
 import SequenceDiagram from './SequenceDiagram.jsx';
 
 class FlowsListEditorView extends Component {
-
-       static propTypes = {
-               flowList: PropTypes.array,
-               currentFlow: PropTypes.object,
-               isDisplayModal: PropTypes.bool,
-               isModalInEditMode: PropTypes.bool,
-               isCheckedOut: PropTypes.bool,
-               shouldShowWorkflowsEditor: PropTypes.bool,
-               readonly: PropTypes.bool,
-
-               onAddWorkflowClick: PropTypes.func,
-               onEditFlowDetailsClick: PropTypes.func,
-               onEditFlowDiagramClick: PropTypes.func,
-               onDeleteFlowClick: PropTypes.func,
-               onSequenceDiagramSaveClick: PropTypes.func,
-               onSequenceDiagramCloseClick: PropTypes.func
-       };
-
-       state = {
-               localFilter: ''
-       };
-
-       render() {
-               let CurrentView = null;
-               if (this.props.shouldShowWorkflowsEditor) {
-                       CurrentView = this.renderWorkflowsEditor();
-               }
-               else {
-                       CurrentView = this.renderSequenceDiagramTool();
-               }
-
-               return CurrentView;
-       }
-
-       renderWorkflowsEditor() {
-               let {isDisplayModal, onAddWorkflowClick, isCheckedOut} = this.props;
-               const {localFilter} = this.state;
-
-               return (
-                       <div className='workflows license-agreement-list-editor'>
-                               <FlowRelatedView display={localFilter}/>
-                               <ListEditorView
-                                       plusButtonTitle={i18n('Add Workflow')}
-                                       onAdd={onAddWorkflowClick}
-                                       filterValue={localFilter}
-                                       onFilter={filter => this.setState({localFilter: filter})}
-                                       isReadOnlyMode={!isCheckedOut}>
-                                       {this.filterList().map(flow => this.renderWorkflowListItem(flow, isCheckedOut))}
-                               </ListEditorView>
-
-                               {isDisplayModal && this.renderWorkflowEditorModal()}
-
-                       </div>
-               );
-       }
-
-       renderWorkflowEditorModal() {
-               let { isDisplayModal, isModalInEditMode} = this.props;
-               return (
-                       <Modal show={isDisplayModal} animation={true} className='onborading-modal workflows-editor-modal'>
-                               <Modal.Header>
-                                       <Modal.Title>
-                                               {`${isModalInEditMode ? i18n('Edit Workflow') : i18n('Create New Workflow')}`}
-                                       </Modal.Title>
-                               </Modal.Header>
-                               <Modal.Body>
-                                       <FlowsEditorModal isNewArtifact={!isModalInEditMode}/>
-                               </Modal.Body>
-                       </Modal>
-               );
-       }
-
-       renderSequenceDiagramTool() {
-               let {onSequenceDiagramSaveClick, onSequenceDiagramCloseClick, currentFlow} = this.props;
-               return (
-                       <SequenceDiagram
-                               onSave={sequenceDiagramModel => onSequenceDiagramSaveClick({...currentFlow, sequenceDiagramModel})}
-                               onClose={onSequenceDiagramCloseClick}
-                               model={currentFlow.sequenceDiagramModel}/>
-               );
-       }
-
-       filterList() {
-               let {flowList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return flowList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return flowList;
-               }
-       }
-
-       renderWorkflowListItem(flow, isCheckedOut) {
-               let {uniqueId, artifactName, description} = flow;
-               let {onEditFlowDetailsClick, onEditFlowDiagramClick, onDeleteFlowClick} = this.props;
-               return (
-                       <ListEditorItemView
-                               key={uniqueId}
-                               onSelect={() => onEditFlowDetailsClick(flow)}
-                               onDelete={() => onDeleteFlowClick(flow)}
-                               onEdit={() => onEditFlowDiagramClick(flow)}
-                               className='list-editor-item-view'
-                               isCheckedOut={isCheckedOut}>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div className='text name'>{artifactName}</div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Description')}</div>
-                                       <div className='text description'>{description}</div>
-                               </div>
-                       </ListEditorItemView>
-               );
-       }
-
+    static propTypes = {
+        flowList: PropTypes.array,
+        currentFlow: PropTypes.object,
+        isDisplayModal: PropTypes.bool,
+        isModalInEditMode: PropTypes.bool,
+        isCheckedOut: PropTypes.bool,
+        shouldShowWorkflowsEditor: PropTypes.bool,
+        readonly: PropTypes.bool,
+
+        onAddWorkflowClick: PropTypes.func,
+        onEditFlowDetailsClick: PropTypes.func,
+        onEditFlowDiagramClick: PropTypes.func,
+        onDeleteFlowClick: PropTypes.func,
+        onSequenceDiagramSaveClick: PropTypes.func,
+        onSequenceDiagramCloseClick: PropTypes.func
+    };
+
+    state = {
+        localFilter: ''
+    };
+
+    render() {
+        let CurrentView = null;
+        if (this.props.shouldShowWorkflowsEditor) {
+            CurrentView = this.renderWorkflowsEditor();
+        } else {
+            CurrentView = this.renderSequenceDiagramTool();
+        }
+
+        return CurrentView;
+    }
+
+    renderWorkflowsEditor() {
+        let { isDisplayModal, onAddWorkflowClick, isCheckedOut } = this.props;
+        const { localFilter } = this.state;
+
+        return (
+            <div className="workflows license-agreement-list-editor">
+                <FlowRelatedView display={localFilter} />
+                <ListEditorView
+                    plusButtonTitle={i18n('Add Workflow')}
+                    onAdd={onAddWorkflowClick}
+                    filterValue={localFilter}
+                    onFilter={filter => this.setState({ localFilter: filter })}
+                    isReadOnlyMode={!isCheckedOut}>
+                    {this.filterList().map(flow =>
+                        this.renderWorkflowListItem(flow, isCheckedOut)
+                    )}
+                </ListEditorView>
+
+                {isDisplayModal && this.renderWorkflowEditorModal()}
+            </div>
+        );
+    }
+
+    renderWorkflowEditorModal() {
+        let { isDisplayModal, isModalInEditMode } = this.props;
+        return (
+            <Modal
+                show={isDisplayModal}
+                animation={true}
+                className="onborading-modal workflows-editor-modal">
+                <Modal.Header>
+                    <Modal.Title>
+                        {`${
+                            isModalInEditMode
+                                ? i18n('Edit Workflow')
+                                : i18n('Create New Workflow')
+                        }`}
+                    </Modal.Title>
+                </Modal.Header>
+                <Modal.Body>
+                    <FlowsEditorModal isNewArtifact={!isModalInEditMode} />
+                </Modal.Body>
+            </Modal>
+        );
+    }
+
+    renderSequenceDiagramTool() {
+        let {
+            onSequenceDiagramSaveClick,
+            onSequenceDiagramCloseClick,
+            currentFlow
+        } = this.props;
+        return (
+            <SequenceDiagram
+                onSave={sequenceDiagramModel =>
+                    onSequenceDiagramSaveClick({
+                        ...currentFlow,
+                        sequenceDiagramModel
+                    })
+                }
+                onClose={onSequenceDiagramCloseClick}
+                model={currentFlow.sequenceDiagramModel}
+            />
+        );
+    }
+
+    filterList() {
+        let { flowList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return flowList.filter(({ name = '', description = '' }) => {
+                return (
+                    escape(name).match(filter) ||
+                    escape(description).match(filter)
+                );
+            });
+        } else {
+            return flowList;
+        }
+    }
+
+    renderWorkflowListItem(flow, isCheckedOut) {
+        let { uniqueId, artifactName, description } = flow;
+        let {
+            onEditFlowDetailsClick,
+            onEditFlowDiagramClick,
+            onDeleteFlowClick
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={uniqueId}
+                onSelect={() => onEditFlowDetailsClick(flow)}
+                onDelete={() => onDeleteFlowClick(flow)}
+                onEdit={() => onEditFlowDiagramClick(flow)}
+                className="list-editor-item-view"
+                isCheckedOut={isCheckedOut}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div className="text name">{artifactName}</div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Description')}</div>
+                    <div className="text description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
 }
 
 export default FlowsListEditorView;
index 14bf595..0279824 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, FLOWS_EDITOR_FORM} from './FlowsConstants.js';
+import { actionTypes, FLOWS_EDITOR_FORM } from './FlowsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.FLOW_LIST_LOADED:
-                       return {
-                               ...state,
-                               flowList: action.results,
-                               flowParticipants: action.participants,
-                               serviceID: action.serviceID,
-                               diagramType: action.diagramType,
-                               readonly: action.readonly
-                       };
-               case actionTypes.ADD_OR_UPDATE_FLOW:
-               case actionTypes.ARTIFACT_LOADED:
-                       let flowList = state.flowList || [];
-                       let index = flowList.findIndex(flow => flow.uniqueId === action.flow.uniqueId);
-                       if (index === -1) {
-                               index = flowList.length;
-                       }
-                       let flowToBeUpdated = flowList[index];
-                       flowList = [
-                               ...flowList.slice(0, index),
-                               {...flowToBeUpdated, ...action.flow},
-                               ...flowList.slice(index + 1)
-                       ];
-                       return {
-                               ...state,
-                               flowList,
-                               serviceID: action.flow.serviceID,
-                               diagramType: action.flow.artifactType || state.diagramType
-                       };
-               case actionTypes.DELETE_FLOW:
-                       return {
-                               ...state,
-                               flowList: state.flowList.filter(flow => flow.uniqueId !== action.flow.uniqueId)
-                       };
-               case actionTypes.OPEN_FLOW_DETAILS_EDITOR:
-                       return {
-                               ...state,
-                               formName: FLOWS_EDITOR_FORM,
-                               formReady: null,
-                               genericFieldInfo: {
-                                       artifactName : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       description: {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       }
-                               },
-                               data: action.flow,
-                               isDisplayModal: true,
-                               isModalInEditMode: Boolean(action.flow && action.flow.uniqueId)
-                       };
+    switch (action.type) {
+        case actionTypes.FLOW_LIST_LOADED:
+            return {
+                ...state,
+                flowList: action.results,
+                flowParticipants: action.participants,
+                serviceID: action.serviceID,
+                diagramType: action.diagramType,
+                readonly: action.readonly
+            };
+        case actionTypes.ADD_OR_UPDATE_FLOW:
+        case actionTypes.ARTIFACT_LOADED:
+            let flowList = state.flowList || [];
+            let index = flowList.findIndex(
+                flow => flow.uniqueId === action.flow.uniqueId
+            );
+            if (index === -1) {
+                index = flowList.length;
+            }
+            let flowToBeUpdated = flowList[index];
+            flowList = [
+                ...flowList.slice(0, index),
+                { ...flowToBeUpdated, ...action.flow },
+                ...flowList.slice(index + 1)
+            ];
+            return {
+                ...state,
+                flowList,
+                serviceID: action.flow.serviceID,
+                diagramType: action.flow.artifactType || state.diagramType
+            };
+        case actionTypes.DELETE_FLOW:
+            return {
+                ...state,
+                flowList: state.flowList.filter(
+                    flow => flow.uniqueId !== action.flow.uniqueId
+                )
+            };
+        case actionTypes.OPEN_FLOW_DETAILS_EDITOR:
+            return {
+                ...state,
+                formName: FLOWS_EDITOR_FORM,
+                formReady: null,
+                genericFieldInfo: {
+                    artifactName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    }
+                },
+                data: action.flow,
+                isDisplayModal: true,
+                isModalInEditMode: Boolean(action.flow && action.flow.uniqueId)
+            };
 
-               case actionTypes.CLOSE_FLOW_DETAILS_EDITOR:
-                       return {
-                               ...state,
-                               data: undefined,
-                               isDisplayModal: false,
-                               isModalInEditMode: false
-                       };
-               case actionTypes.OPEN_FLOW_DIAGRAM_EDITOR:
-                       return {
-                               ...state,
-                               data: action.flow,
-                               shouldShowWorkflowsEditor: false
-                       };
-               case actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR:
-                       return {
-                               ...state,
-                               data: undefined,
-                               shouldShowWorkflowsEditor: true
-                       };
-               case actionTypes.RESET:
-                       return {};
-       }
+        case actionTypes.CLOSE_FLOW_DETAILS_EDITOR:
+            return {
+                ...state,
+                data: undefined,
+                isDisplayModal: false,
+                isModalInEditMode: false
+            };
+        case actionTypes.OPEN_FLOW_DIAGRAM_EDITOR:
+            return {
+                ...state,
+                data: action.flow,
+                shouldShowWorkflowsEditor: false
+            };
+        case actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR:
+            return {
+                ...state,
+                data: undefined,
+                shouldShowWorkflowsEditor: true
+            };
+        case actionTypes.RESET:
+            return {};
+    }
 
-       return state;
+    return state;
 };
index a2a5554..7d30244 100644 (file)
@@ -22,57 +22,66 @@ import FlowsListEditor from './FlowsListEditor.js';
 import FlowsActions from './FlowsActions.js';
 
 class FlowsListEditorPunchOutWrapper extends React.Component {
+    componentDidMount() {
+        let element = ReactDOM.findDOMNode(this);
+        element.addEventListener('click', event => {
+            if (event.target.tagName === 'A') {
+                event.preventDefault();
+            }
+        });
+        ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
+            element.addEventListener(eventType, event =>
+                event.stopPropagation()
+            )
+        );
+    }
 
-       componentDidMount() {
-               let element = ReactDOM.findDOMNode(this);
-               element.addEventListener('click', event => {
-                       if (event.target.tagName === 'A') {
-                               event.preventDefault();
-                       }
-               });
-               ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
-                       element.addEventListener(eventType, event => event.stopPropagation())
-               );
-       }
-
-       render() {
-               return <FlowsListEditor/>;
-       }
+    render() {
+        return <FlowsListEditor />;
+    }
 }
 
 export default class DiagramPunchOut {
+    render({ options: { data, apiRoot, apiHeaders }, onEvent }, element) {
+        if (!this.isConfigSet) {
+            Configuration.setCatalogApiRoot(apiRoot);
+            Configuration.setCatalogApiHeaders(apiHeaders);
+            this.isConfigSet = true;
+        }
 
-       render({options: {data, apiRoot, apiHeaders}, onEvent}, element) {
-
-               if (!this.isConfigSet) {
-                       Configuration.setCatalogApiRoot(apiRoot);
-                       Configuration.setCatalogApiHeaders(apiHeaders);
-                       this.isConfigSet = true;
-               }
-
-               this.onEvent = onEvent;
-               this.handleData(data);
+        this.onEvent = onEvent;
+        this.handleData(data);
 
-               if (!this.rendered) {
-                       ReactDOM.render(<Application><div className='dox-ui'><FlowsListEditorPunchOutWrapper/></div></Application>, element);
-                       this.rendered = true;
-               }
-       }
+        if (!this.rendered) {
+            ReactDOM.render(
+                <Application>
+                    <div className="dox-ui">
+                        <FlowsListEditorPunchOutWrapper />
+                    </div>
+                </Application>,
+                element
+            );
+            this.rendered = true;
+        }
+    }
 
-       unmount(element) {
-               let dispatch = action => store.dispatch(action);
-               ReactDOM.unmountComponentAtNode(element);
-               FlowsActions.reset(dispatch);
-       }
+    unmount(element) {
+        let dispatch = action => store.dispatch(action);
+        ReactDOM.unmountComponentAtNode(element);
+        FlowsActions.reset(dispatch);
+    }
 
-       handleData(data) {
-               let {serviceID, diagramType} = data;
-               let dispatch = action => store.dispatch(action);
+    handleData(data) {
+        let { serviceID, diagramType } = data;
+        let dispatch = action => store.dispatch(action);
 
-               if (serviceID !== this.prevServiceID || diagramType !== this.prevDiagramType) {
-                       this.prevServiceID = serviceID;
-                       this.prevDiagramType = diagramType;
-                       FlowsActions.fetchFlowArtifacts(dispatch, {...data});
-               }
-       }
+        if (
+            serviceID !== this.prevServiceID ||
+            diagramType !== this.prevDiagramType
+        ) {
+            this.prevServiceID = serviceID;
+            this.prevDiagramType = diagramType;
+            FlowsActions.fetchFlowArtifacts(dispatch, { ...data });
+        }
+    }
 }
index 5404349..c037f3e 100644 (file)
@@ -15,8 +15,8 @@
  */
 
 import flowListReducer from './FlowsListReducer.js';
-import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
+import { createPlainDataReducer } from 'sdc-app/common/reducers/PlainDataReducer.js';
 
 export default {
-       flows: createPlainDataReducer(flowListReducer)
+    flows: createPlainDataReducer(flowListReducer)
 };
index d0a5bf3..8a63491 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import md5 from 'md5';
 
 class ImportantLogic extends Component {
+    state = {
+        whatToDisplay: false
+    };
 
-       state = {
-               whatToDisplay: false
-       };
+    componentWillReceiveProps(nextProps) {
+        this.setState({
+            whatToDisplay:
+                md5(nextProps.display) === 'a55899b341525123628776dbf5755d51'
+        });
+    }
 
-       componentWillReceiveProps(nextProps) {
-               this.setState({whatToDisplay: md5(nextProps.display) === 'a55899b341525123628776dbf5755d51'});
-       }
+    render() {
+        if (this.state.whatToDisplay) {
+            setTimeout(() => this.setState({ whatToDisplay: false }), 5000);
+        }
 
-       render() {
-               if (this.state.whatToDisplay) {
-                       setTimeout(() => this.setState({whatToDisplay: false}), 5000);
-               }
-
-               return (
-                       <div>
-                               <style>{'\.easter-wrapper {\
+        return (
+            <div>
+                <style>
+                    {
+                        '.easter-wrapper {\
                                        position: fixed;\
                                        width: 70px;\
                                        height: 70px;\
@@ -96,16 +100,20 @@ class ImportantLogic extends Component {
                                        @keyframes yo-yo {\
                                        from { transform: rotate(-0deg); top: 0 }\
                                        to { transform: rotate(-360deg); top:120px }\
-                               }'}</style>
-                               <div
-                                       className='easter-wrapper'
-                                       style={{display: this.state.whatToDisplay ? 'block' : 'none'}}>
-                                       <span className='string'>{}</span>
-                                       <span className='yo-yo'>{}</span>
-                               </div>
-                       </div>
-               );
-       }
+                               }'
+                    }
+                </style>
+                <div
+                    className="easter-wrapper"
+                    style={{
+                        display: this.state.whatToDisplay ? 'block' : 'none'
+                    }}>
+                    <span className="string">{}</span>
+                    <span className="yo-yo">{}</span>
+                </div>
+            </div>
+        );
+    }
 }
 
 export default ImportantLogic;
index c128083..ca24964 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import Button from 'sdc-ui/lib/react/Button.js';
 import Sequencer from 'dox-sequence-diagram-ui';
@@ -21,31 +21,37 @@ import Sequencer from 'dox-sequence-diagram-ui';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 class SequenceDiagram extends Component {
+    static propTypes = {
+        onSave: PropTypes.func.isRequired,
+        onClose: PropTypes.func,
+        model: PropTypes.object.isRequired
+    };
 
-       static propTypes = {
-               onSave: PropTypes.func.isRequired,
-               onClose: PropTypes.func,
-               model: PropTypes.object.isRequired
-       };
-
-       onSave() {
-               this.props.onSave(this.refs.sequencer.getModel());
-       }
-
-       render() {
-               return (
-                       <div className='sequence-diagram'>
-                               <div className='sequence-diagram-sequencer'>
-                                       <Sequencer ref='sequencer' options={{useHtmlSelect: true}} model={this.props.model} />
-                               </div>
-                               <div className='sequence-diagram-action-buttons'>
-                                       <Button onClick={() => this.onSave()}>{i18n('Save')}</Button>
-                                       <Button onClick={this.props.onClose}>{i18n('Close')}</Button>
-                               </div>
-                       </div>
-               );
-       }
+    onSave() {
+        this.props.onSave(this.refs.sequencer.getModel());
+    }
 
+    render() {
+        return (
+            <div className="sequence-diagram">
+                <div className="sequence-diagram-sequencer">
+                    <Sequencer
+                        ref="sequencer"
+                        options={{ useHtmlSelect: true }}
+                        model={this.props.model}
+                    />
+                </div>
+                <div className="sequence-diagram-action-buttons">
+                    <Button onClick={() => this.onSave()}>
+                        {i18n('Save')}
+                    </Button>
+                    <Button onClick={this.props.onClose}>
+                        {i18n('Close')}
+                    </Button>
+                </div>
+            </div>
+        );
+    }
 }
 
 export default SequenceDiagram;
index c83fdc9..23723dc 100644 (file)
 import emptyModel from './emptyModel.json';
 
 function mergeLifelines(oldLifelines, newLifelines) {
-       let oldLifelinesMap = new Map(oldLifelines.map(lifeline => [lifeline.id, lifeline]));
-       let newLifelinesMap = new Map(newLifelines.map(lifeline => [lifeline.id, lifeline]));
+    let oldLifelinesMap = new Map(
+        oldLifelines.map(lifeline => [lifeline.id, lifeline])
+    );
+    let newLifelinesMap = new Map(
+        newLifelines.map(lifeline => [lifeline.id, lifeline])
+    );
 
-       let updatedLifelines = oldLifelines.map(lifeline => {
-               let newLifeline = newLifelinesMap.get(lifeline.id);
-               return {
-                       ...lifeline,
-                       name: newLifeline ? newLifeline.name : lifeline.name
-               };
-       });
+    let updatedLifelines = oldLifelines.map(lifeline => {
+        let newLifeline = newLifelinesMap.get(lifeline.id);
+        return {
+            ...lifeline,
+            name: newLifeline ? newLifeline.name : lifeline.name
+        };
+    });
 
-       let addedLifelines = newLifelines.filter(lifeline => !oldLifelinesMap.has(lifeline.id));
+    let addedLifelines = newLifelines.filter(
+        lifeline => !oldLifelinesMap.has(lifeline.id)
+    );
 
-       return [
-               ...updatedLifelines,
-               ...addedLifelines
-       ];
+    return [...updatedLifelines, ...addedLifelines];
 }
 
-
 const SequenceDiagramModelHelper = Object.freeze({
+    createModel(options) {
+        return SequenceDiagramModelHelper.updateModel(emptyModel, options);
+    },
 
-       createModel(options) {
-               return SequenceDiagramModelHelper.updateModel(emptyModel, options);
-       },
-
-       updateModel(model, options) {
-               const diagram = model.diagram;
-               const metadata = diagram.metadata || model.metadata;
-               const id = options.id || metadata.id;
-               const name = options.name || metadata.name;
-               const lifelines = options.lifelines ? mergeLifelines(diagram.lifelines, options.lifelines) : diagram.lifelines;
+    updateModel(model, options) {
+        const diagram = model.diagram;
+        const metadata = diagram.metadata || model.metadata;
+        const id = options.id || metadata.id;
+        const name = options.name || metadata.name;
+        const lifelines = options.lifelines
+            ? mergeLifelines(diagram.lifelines, options.lifelines)
+            : diagram.lifelines;
 
-               return {
-                       diagram: {
-                               ...diagram,
-                               metadata: {
-                                       ...metadata,
-                                       id,
-                                       name
-                               },
-                               lifelines
-                       }
-               };
-       }
+        return {
+            diagram: {
+                ...diagram,
+                metadata: {
+                    ...metadata,
+                    id,
+                    name
+                },
+                lifelines
+            }
+        };
+    }
 });
 
 export default SequenceDiagramModelHelper;
index 5abe309..bb9a4bb 100644 (file)
@@ -23,5 +23,9 @@ import ReactDOM from 'react-dom';
 import UploadScreen from './heatvalidation/UploadScreen.jsx';
 import Application from './Application.jsx';
 
-
-ReactDOM.render(<Application openSocket={false}><UploadScreen/></Application>, document.getElementById('heat-validation-app'));
+ReactDOM.render(
+    <Application openSocket={false}>
+        <UploadScreen />
+    </Application>,
+    document.getElementById('heat-validation-app')
+);
index d3e30b0..4532c0a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
-import {mapStateToProps as attachmentsMapStateToProps, mapActionsToProps as attachmentsMapActionsToProps} from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js';
+import {
+    mapStateToProps as attachmentsMapStateToProps,
+    mapActionsToProps as attachmentsMapActionsToProps
+} from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js';
 // import AttachmentsView from './AttachmentsView.jsx';
 import AttachmentsView from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx';
 import UploadScreenActionHelper from './UploadScreenActionHelper.js';
 import HeatSetup from './HeatSetup';
 
-export const mapStateToProps = (state) => {
-       let original = attachmentsMapStateToProps(state);
-       return {
-               ...original,
-               HeatSetupComponent: HeatSetup,
-               isReadOnlyMode: false
-       };
+export const mapStateToProps = state => {
+    let original = attachmentsMapStateToProps(state);
+    return {
+        ...original,
+        HeatSetupComponent: HeatSetup,
+        isReadOnlyMode: false
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId}) => {
-       let original = attachmentsMapActionsToProps(dispatch, {softwareProductId});
-       return {
-               ...original,
-               onDownload: heatCandidate => UploadScreenActionHelper.downloadHeatFile(dispatch, heatCandidate),
-               onUpload: formData => UploadScreenActionHelper.uploadFile(dispatch, formData),
-               onSave: (heatCandidate) => SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate}),
-               onProcessAndValidate: (heatData, heatDataCache) => UploadScreenActionHelper.processAndValidateHeat(dispatch, heatData, heatDataCache)
-       };
+const mapActionsToProps = (dispatch, { softwareProductId }) => {
+    let original = attachmentsMapActionsToProps(dispatch, {
+        softwareProductId
+    });
+    return {
+        ...original,
+        onDownload: heatCandidate =>
+            UploadScreenActionHelper.downloadHeatFile(dispatch, heatCandidate),
+        onUpload: formData =>
+            UploadScreenActionHelper.uploadFile(dispatch, formData),
+        onSave: heatCandidate =>
+            SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(
+                dispatch,
+                {
+                    softwareProductId,
+                    heatCandidate
+                }
+            ),
+        onProcessAndValidate: (heatData, heatDataCache) =>
+            UploadScreenActionHelper.processAndValidateHeat(
+                dispatch,
+                heatData,
+                heatDataCache
+            )
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(AttachmentsView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(AttachmentsView);
index 925b009..a94cfd9 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
-import HeatSetupView  from '../onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx';
+import { connect } from 'react-redux';
+import HeatSetupView from '../onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx';
 import UploadScreenActionHelper from './UploadScreenActionHelper.js';
-import {mapStateToProps, mapActionsToProps} from '../onboarding/softwareProduct/attachments/setup/HeatSetup.js';
+import {
+    mapStateToProps,
+    mapActionsToProps
+} from '../onboarding/softwareProduct/attachments/setup/HeatSetup.js';
 
-const mapActionsToPropsExt = (dispatch) => {
-       return {
-               ...mapActionsToProps(dispatch,{}),
-               onProcessAndValidate: (heatData, heatDataCache) => UploadScreenActionHelper.processAndValidateHeat(dispatch, heatData, heatDataCache)
-       };
+const mapActionsToPropsExt = dispatch => {
+    return {
+        ...mapActionsToProps(dispatch, {}),
+        onProcessAndValidate: (heatData, heatDataCache) =>
+            UploadScreenActionHelper.processAndValidateHeat(
+                dispatch,
+                heatData,
+                heatDataCache
+            )
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToPropsExt, null, {withRef: true})(HeatSetupView);
+export default connect(mapStateToProps, mapActionsToPropsExt, null, {
+    withRef: true
+})(HeatSetupView);
index 2d99c0f..6d3d54b 100644 (file)
 import React from 'react';
 import SoftwareProductAttachmentsView from './Attachments.js';
 
-
-
 class UploadScreen extends React.Component {
-
-       render() {
-               return(
-                       <div className='heat-validation-stand-alone'>
-                               <SoftwareProductAttachmentsView />
-                       </div>
-               );
-       }
+    render() {
+        return (
+            <div className="heat-validation-stand-alone">
+                <SoftwareProductAttachmentsView />
+            </div>
+        );
+    }
 }
 
-export default  UploadScreen;
+export default UploadScreen;
index fa2d469..f5d9abd 100644 (file)
@@ -18,155 +18,197 @@ import showFileSaveDialog from 'nfvo-utils/ShowFileSaveDialog.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import isEqual from 'lodash/isEqual.js';
 import cloneDeep from 'lodash/cloneDeep.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes as softwareProductsActionTypes} from '../onboarding/softwareProduct/SoftwareProductConstants.js';
-import {actionTypes as HeatSetupActions} from '../onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
-
-
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes as softwareProductsActionTypes } from '../onboarding/softwareProduct/SoftwareProductConstants.js';
+import { actionTypes as HeatSetupActions } from '../onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
 
 const options = {
-       headers: {
-               USER_ID: 'validationOnlyVspUser'
-       }
+    headers: {
+        USER_ID: 'validationOnlyVspUser'
+    }
 };
 
 function fetchVspIdAndVersion() {
-
-       let vspId = sessionStorage.getItem('validationAppVspId');
-       let versionId = sessionStorage.getItem('validationAppVersionId');
-       if (vspId) {
-               return  Promise.resolve({value: vspId, versionId});
-       }else {
-               return RestAPIUtil.fetch('/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/validation-vsp', options)
-                       .then(response => {
-                               sessionStorage.setItem('validationAppVspId', response.itemId);
-                               sessionStorage.setItem('validationAppVersionId', response.version.id);
-                               return Promise.resolve({value: response.itemId, versionId: response.version.id});
-                       });
-       }
-
+    let vspId = sessionStorage.getItem('validationAppVspId');
+    let versionId = sessionStorage.getItem('validationAppVersionId');
+    if (vspId) {
+        return Promise.resolve({ value: vspId, versionId });
+    } else {
+        return RestAPIUtil.fetch(
+            '/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/validation-vsp',
+            options
+        ).then(response => {
+            sessionStorage.setItem('validationAppVspId', response.itemId);
+            sessionStorage.setItem(
+                'validationAppVersionId',
+                response.version.id
+            );
+            return Promise.resolve({
+                value: response.itemId,
+                versionId: response.version.id
+            });
+        });
+    }
 }
 
-
 function uploadFile(formData) {
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       return RestAPIUtil.post(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}/orchestration-template-candidate`, formData, options);
-               });
+    return fetchVspIdAndVersion().then(response => {
+        return RestAPIUtil.post(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${response.versionId}/orchestration-template-candidate`,
+            formData,
+            options
+        );
+    });
 }
 
-function loadSoftwareProductHeatCandidate(dispatch){
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       return RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}/orchestration-template-candidate/manifest`, options)
-                               .then(response => dispatch({
-                                       type: HeatSetupActions.MANIFEST_LOADED,
-                                       response
-                               }));
-               });
+function loadSoftwareProductHeatCandidate(dispatch) {
+    return fetchVspIdAndVersion().then(response => {
+        return RestAPIUtil.fetch(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${
+                response.versionId
+            }/orchestration-template-candidate/manifest`,
+            options
+        ).then(response =>
+            dispatch({
+                type: HeatSetupActions.MANIFEST_LOADED,
+                response
+            })
+        );
+    });
 }
 
 function updateHeatCandidate(dispatch, heatCandidate) {
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       return RestAPIUtil.put(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}/orchestration-template-candidate/manifest`,
-                               heatCandidate.heatData, options)
-                               .then(null, error => {
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                                               data: {
-                                                       title: i18n('Save Failed'), 
-                                                       modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE,                                                   
-                                                       modalComponentProps: {
-                                                               validationResponse: error.responseJSON
-                                                       },                                      
-                                                       cancelButtonText: i18n('Ok')
-                                               }
-                                       });
-                                       return Promise.reject(error);
-                               });
-               });
+    return fetchVspIdAndVersion().then(response => {
+        return RestAPIUtil.put(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${
+                response.versionId
+            }/orchestration-template-candidate/manifest`,
+            heatCandidate.heatData,
+            options
+        ).then(null, error => {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                data: {
+                    title: i18n('Save Failed'),
+                    modalComponentName:
+                        modalContentMapper.SUMBIT_ERROR_RESPONSE,
+                    modalComponentProps: {
+                        validationResponse: error.responseJSON
+                    },
+                    cancelButtonText: i18n('Ok')
+                }
+            });
+            return Promise.reject(error);
+        });
+    });
 }
 
 function fetchSoftwareProduct() {
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       return RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}`, options);
-               });
+    return fetchVspIdAndVersion().then(response => {
+        return RestAPIUtil.fetch(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${response.versionId}`,
+            options
+        );
+    });
 }
 
 function downloadHeatFile() {
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}/orchestration-template-candidate`, {
-                               ...options,
-                               dataType: 'binary'
-                       })
-                               .done((response) => showFileSaveDialog({
-                                       blob: response.blob,
-                                       headers: response.headers,
-                                       defaultFilename: 'HEAT_file.zip',
-                                       addTimestamp: true
-                               }));
-               });
+    return fetchVspIdAndVersion().then(response => {
+        RestAPIUtil.fetch(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${response.versionId}/orchestration-template-candidate`,
+            {
+                ...options,
+                dataType: 'binary'
+            }
+        ).done(response =>
+            showFileSaveDialog({
+                blob: response.blob,
+                headers: response.headers,
+                defaultFilename: 'HEAT_file.zip',
+                addTimestamp: true
+            })
+        );
+    });
 }
 
 function processAndValidateHeatCandidate(dispatch) {
-       return fetchVspIdAndVersion()
-               .then(response => {
-                       return RestAPIUtil.put(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/${response.versionId}/orchestration-template-candidate/process`, {}, options)
-                               .then(response => {
-                                       if (response.status === 'Success') {
-                                               fetchSoftwareProduct().then(response => {
-                                                       dispatch({
-                                                               type: softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
-                                                               response
-                                                       });
-                                               });
-                                       }
-                               });
-               });
+    return fetchVspIdAndVersion().then(response => {
+        return RestAPIUtil.put(
+            `/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${
+                response.value
+            }/versions/${
+                response.versionId
+            }/orchestration-template-candidate/process`,
+            {},
+            options
+        ).then(response => {
+            if (response.status === 'Success') {
+                fetchSoftwareProduct().then(response => {
+                    dispatch({
+                        type:
+                            softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
+                        response
+                    });
+                });
+            }
+        });
+    });
 }
 
 const UploadScreenActionHelper = {
-       uploadFile(dispatch, formData) {
-
-               return Promise.resolve()
-                       .then(() => uploadFile(formData))
-                       .then(response => {
-                               dispatch({
-                                       type: softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
-                                       response
-                               });
-                               dispatch({
-                                       type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
-                                       payload:{}
-                               });
-                               loadSoftwareProductHeatCandidate(dispatch);
-                       })
-                       .catch(error => {
-                               dispatch({                                      
-                                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                                       data: {
-                                               title: i18n('File Upload Failed'),                                                                                                      
-                                               msg: error.responseJSON.message,                                        
-                                               cancelButtonText: i18n('Ok')
-                                       }
-                               });
-                       });
-       },
-
-       processAndValidateHeat(dispatch, heatData, heatDataCache){
-               return isEqual(heatData, heatDataCache) ? Promise.resolve() :
-                       updateHeatCandidate(dispatch, heatData)
-                               .then(() => processAndValidateHeatCandidate(dispatch))
-                               .then(() => dispatch({type: HeatSetupActions.FILL_HEAT_SETUP_CACHE, payload: cloneDeep(heatData)}));
-       },
-
-       downloadHeatFile(){
-               return downloadHeatFile();
-       },
+    uploadFile(dispatch, formData) {
+        return Promise.resolve()
+            .then(() => uploadFile(formData))
+            .then(response => {
+                dispatch({
+                    type: softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
+                    response
+                });
+                dispatch({
+                    type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
+                    payload: {}
+                });
+                loadSoftwareProductHeatCandidate(dispatch);
+            })
+            .catch(error => {
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                    data: {
+                        title: i18n('File Upload Failed'),
+                        msg: error.responseJSON.message,
+                        cancelButtonText: i18n('Ok')
+                    }
+                });
+            });
+    },
+
+    processAndValidateHeat(dispatch, heatData, heatDataCache) {
+        return isEqual(heatData, heatDataCache)
+            ? Promise.resolve()
+            : updateHeatCandidate(dispatch, heatData)
+                  .then(() => processAndValidateHeatCandidate(dispatch))
+                  .then(() =>
+                      dispatch({
+                          type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
+                          payload: cloneDeep(heatData)
+                      })
+                  );
+    },
+
+    downloadHeatFile() {
+        return downloadHeatFile();
+    }
 };
 
 export default UploadScreenActionHelper;
index 81a29cf..7b8c87e 100644 (file)
 import React from 'react';
-import {storiesOf} from '@kadira/storybook';
-import {withKnobs} from '@kadira/storybook-addon-knobs';
+import { storiesOf } from '@kadira/storybook';
+import { withKnobs } from '@kadira/storybook-addon-knobs';
 
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-
 const stories = storiesOf('GridColumns', module);
 stories.addDecorator(withKnobs);
 
 var divStyle = {
-       'border-style': 'solid',
-       'border-size': 1
+    'border-style': 'solid',
+    'border-size': 1
 };
 
-const myDiv =  (<div style={divStyle}>Text Text Text</div>);
+const myDiv = <div style={divStyle}>Text Text Text</div>;
 
 stories
-       .add('Grid Options', () => (
-               <div>
-                       <GridSection title='No last column set on item'>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-
-                       <GridSection hasLastColSet={true} title='With last column set on item and gridsection'>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-
-                       <GridSection title='With last column set on item and NOT on gridsection'>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
+    .add('Grid Options', () => (
+        <div>
+            <GridSection title="No last column set on item">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+            </GridSection>
 
-               </div>
-       ))
-       .add('Last Column', () => (
+            <GridSection
+                hasLastColSet={true}
+                title="With last column set on item and gridsection">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
 
-               <div>
-                       <GridSection hasLastColSet={true} title='Testing different configurations with all settings'>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={4} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={3}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection hasLastColSet={true}>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={3} lastColInRow={true}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-               </div>
-       ))
-       .add('No Last Column', () => (
-               <div>
-                       <GridSection title='Testing different configurations'>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={2}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={4}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={3}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-                       <GridSection>
-                               <GridItem colSpan={1}>
-                                       {myDiv}
-                               </GridItem>
-                               <GridItem colSpan={3}>
-                                       {myDiv}
-                               </GridItem>
-                       </GridSection>
-               </div>
-       ))      .add('Test LKG form', () => (
-       <div>
-               <GridSection title='Testing VLM LKG configurations'>
-                       <GridItem colSpan={2}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow={true}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={2}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow={true}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={1}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={1}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={1}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={1} lastColInRow={true}>
-                               {myDiv}
-                       </GridItem>
-                       <GridItem colSpan={2}>
-                               <div style={divStyle}>1</div>
-                       </GridItem>
-               </GridSection>
-       </div>
-));
\ No newline at end of file
+            <GridSection title="With last column set on item and NOT on gridsection">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+        </div>
+    ))
+    .add('Last Column', () => (
+        <div>
+            <GridSection
+                hasLastColSet={true}
+                title="Testing different configurations with all settings">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={4} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={3}>{myDiv}</GridItem>
+                <GridItem colSpan={1} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+            <GridSection hasLastColSet={true}>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={3} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+            </GridSection>
+        </div>
+    ))
+    .add('No Last Column', () => (
+        <div>
+            <GridSection title="Testing different configurations">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={4}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={3}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+            </GridSection>
+            <GridSection>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={3}>{myDiv}</GridItem>
+            </GridSection>
+        </div>
+    ))
+    .add('Test LKG form', () => (
+        <div>
+            <GridSection title="Testing VLM LKG configurations">
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+                <GridItem colSpan={2}>{myDiv}</GridItem>
+                <GridItem colSpan={2} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1}>{myDiv}</GridItem>
+                <GridItem colSpan={1} lastColInRow={true}>
+                    {myDiv}
+                </GridItem>
+                <GridItem colSpan={2}>
+                    <div style={divStyle}>1</div>
+                </GridItem>
+            </GridSection>
+        </div>
+    ));
index faec816..b894e3f 100644 (file)
@@ -15,8 +15,8 @@
  */
 
 import OnboardingView from './OnboardingView.jsx';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
-const mapStateToProps = ({currentScreen}) => ({currentScreen});
+const mapStateToProps = ({ currentScreen }) => ({ currentScreen });
 const Onboarding = connect(mapStateToProps, null)(OnboardingView);
 export default Onboarding;
index d75c234..2fccfcb 100644 (file)
@@ -34,289 +34,591 @@ import ComputeFlavorActionHelper from './softwareProduct/components/compute/Comp
 import OnboardActionHelper from './onboard/OnboardActionHelper.js';
 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
 import SoftwareProductComponentsMonitoringAction from './softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js';
-import {actionTypes, enums} from './OnboardingConstants.js';
-import {actionTypes as SoftwareProductActionTypes, onboardingOriginTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { actionTypes, enums } from './OnboardingConstants.js';
+import {
+    actionTypes as SoftwareProductActionTypes,
+    onboardingOriginTypes
+} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 import ActivityLogActionHelper from 'sdc-app/common/activity-log/ActivityLogActionHelper.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 import SoftwareProductComponentsImageActionHelper from './softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js';
 import licenseModelOverviewActionHelper from 'sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js';
-import {tabsMapping as attachmentsTabsMapping} from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js';
+import { tabsMapping as attachmentsTabsMapping } from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js';
 import SoftwareProductAttachmentsActionHelper from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js';
 
 function setCurrentScreen(dispatch, screen, props = {}) {
-       dispatch({
-               type: actionTypes.SET_CURRENT_SCREEN,
-               currentScreen: {
-                       screen,
-                       props,
-                       forceBreadCrumbsUpdate: true
-               }
-       });
+    dispatch({
+        type: actionTypes.SET_CURRENT_SCREEN,
+        currentScreen: {
+            screen,
+            props,
+            forceBreadCrumbsUpdate: true
+        }
+    });
 }
 
 export function updateCurrentScreenProps(dispatch, props = {}) {
-       dispatch({
-               type: actionTypes.UPDATE_CURRENT_SCREEN_PROPS,
-               props
-       });
+    dispatch({
+        type: actionTypes.UPDATE_CURRENT_SCREEN_PROPS,
+        props
+    });
 }
 
 const OnboardingActionHelper = {
-
-       loadItemsLists(dispatch) {
-               LicenseModelActionHelper.fetchLicenseModels(dispatch);
-               LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
-               LicenseModelActionHelper.fetchArchivedLicenseModels(dispatch);
-               SoftwareProductActionHelper.fetchSoftwareProductList(dispatch);
-               SoftwareProductActionHelper.fetchFinalizedSoftwareProductList(dispatch);
-               SoftwareProductActionHelper.fetchArchivedSoftwareProductList(dispatch);
-       },
-
-       navigateToOnboardingCatalog(dispatch) {
-               UsersActionHelper.fetchUsersList(dispatch);
-               this.loadItemsLists(dispatch);
-               OnboardActionHelper.resetOnboardStore(dispatch);
-               setCurrentScreen(dispatch, enums.SCREEN.ONBOARDING_CATALOG);
-       },
-
-       autoSaveBeforeNavigate(dispatch, {softwareProductId, version, vspComponentId, dataToSave}) {
-               if(softwareProductId) {
-                       if(vspComponentId) {
-                               return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch, {
-                                       softwareProductId, version, vspComponentId,
-                                       componentData: dataToSave.componentData,
-                                       qdata: dataToSave.qdata
-                               });
-                       }
-                       return SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
-                               softwareProduct: dataToSave.softwareProduct,
-                               version,
-                               qdata: dataToSave.qdata
-                       });
-               }
-               return Promise.resolve();
-       },
-
-       navigateToLicenseModelOverview(dispatch, {licenseModelId, version, status}) {
-
-               /**
-                * TODO change to specific rest
-                */
-
-               LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
-                       LicenseModelActionHelper.fetchLicenseModelItems(dispatch, {licenseModelId, version}).then(() => {
-                               setCurrentScreen(dispatch, enums.SCREEN.LICENSE_MODEL_OVERVIEW, {licenseModelId, version, status});
-                       });
-                       licenseModelOverviewActionHelper.selectVLMListView(dispatch, {buttonTab: null});
-               });
-       },
-       navigateToLicenseAgreements(dispatch, {licenseModelId, version, status}) {
-               LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
-               LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
-                       setCurrentScreen(dispatch, enums.SCREEN.LICENSE_AGREEMENTS, {licenseModelId, version, status});
-               });
-       },
-
-       navigateToFeatureGroups(dispatch, {licenseModelId, version, status}) {
-               FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.FEATURE_GROUPS, {licenseModelId, version, status});
-       },
-
-       navigateToEntitlementPools(dispatch, {licenseModelId, version, status}) {
-               EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.ENTITLEMENT_POOLS, {licenseModelId, version, status});
-       },
-
-       navigateToLicenseKeyGroups(dispatch, {licenseModelId, version, status}) {
-               LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.LICENSE_KEY_GROUPS, {licenseModelId, version, status});
-       },
-
-       navigateToLicenseModelActivityLog(dispatch, {licenseModelId, version, status}){
-               ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: version.id});
-               setCurrentScreen(dispatch, enums.SCREEN.ACTIVITY_LOG, {licenseModelId, version, status});
-       },
-
-       navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductComponentsActionHelper.clearComponentsStore(dispatch);
-               SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version}).then(response => {
-                       let {vendorId: licenseModelId, licensingVersion} = response[0];
-                       SoftwareProductActionHelper.loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion});
-                       SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version: version});
-                       if(response[0].onboardingOrigin === onboardingOriginTypes.ZIP) {
-                               SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version: version});
-                       }
-                       setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {softwareProductId, licenseModelId, version, status});
-               });
-       },
-
-       navigateToSoftwareProductDetails(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version}).then(response => {
-                       let {vendorId: licenseModelId, licensingVersion} = response[0];
-                       SoftwareProductActionHelper.loadLicensingVersionsList(dispatch, {licenseModelId});
-                       SoftwareProductActionHelper.loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion});
-                       setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, {softwareProductId, version, status});
-               });
-       },
-
-       navigateToSoftwareProductAttachmentsSetupTab(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version});
-               SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {activeTab: attachmentsTabsMapping.SETUP});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, {softwareProductId, version, status});
-       },
-       navigateToSoftwareProductAttachmentsValidationTab(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductActionHelper.processAndValidateHeatCandidate(dispatch, {softwareProductId, version}).then(() => {
-                       SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {activeTab: attachmentsTabsMapping.VALIDATION});
-                       setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, {softwareProductId, version, status});
-               });
-       },
-
-       navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version, status}) {
-               if (softwareProductId) {
-                       SoftwareProductProcessesActionHelper.fetchProcessesList(dispatch, {softwareProductId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, {softwareProductId, version, status});
-       },
-
-       navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version, status}) {
-               if (softwareProductId) {
-                       SoftwareProductNetworksActionHelper.fetchNetworksList(dispatch, {softwareProductId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, {softwareProductId, version, status});
-       },
-
-       navigateToSoftwareProductDependencies(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version}).then(result => {
-                       if(result.listCount >= 2) {
-                               SoftwareProductDependenciesActionHelper.fetchDependencies(dispatch, {softwareProductId, version});
-                               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES, {softwareProductId, version, status});
-                       }
-                       else {
-                               this.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version, status});
-                       }
-               });
-       },
-
-       navigateToSoftwareProductComponents(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, {softwareProductId, version, status});
-       },
-       navigateToSoftwareProductDeployment(dispatch, {softwareProductId, version, status}) {
-               SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version});
-               ComputeFlavorActionHelper.fetchComputesListForVSP(dispatch, {softwareProductId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT, {softwareProductId, version, status});
-       },
-       navigateToSoftwareProductActivityLog(dispatch, {softwareProductId, version, status}){
-               ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: softwareProductId, versionId: version.id});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG, {softwareProductId, version, status});
-       },
-
-       navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId, version, status}) {
-               if (componentId && softwareProductId) {
-                       SoftwareProductComponentProcessesActionHelper.fetchProcessesList(dispatch, {componentId, softwareProductId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES, {softwareProductId, componentId, version, status});
-       },
-
-       navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, version, componentId, status}){
-               if (componentId && softwareProductId && version) {
-                       SoftwareProductComponentsMonitoringAction.fetchExistingFiles(dispatch, {componentId, softwareProductId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING, {softwareProductId, componentId, version, status});
-       },
-
-       navigateToComponentStorage(dispatch, {softwareProductId, componentId, version, status}) {
-               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToComponentCompute(dispatch, {softwareProductId, componentId, version, status}) {
-               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
-               if (componentId && softwareProductId) {
-                       ComputeFlavorActionHelper.fetchComputesList(dispatch, {softwareProductId, componentId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToComponentNetwork(dispatch, {softwareProductId, componentId, version, status}) {
-               SoftwareProductComponentsNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId, version, status}) {
-               if (componentId && softwareProductId) {
-                       SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
-               }
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version, status}) {
-               this.navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId, version, status});
-               dispatch({
-                       type: SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
-                       mapOfExpandedIds: {
-                               [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: true,
-                               [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + '|' + componentId]: true
-                       }
-               });
-       },
-
-       navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId, version, status}) {
-               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToComponentImages(dispatch, {softwareProductId, componentId, version, status}) {
-               SoftwareProductComponentsImageActionHelper.fetchImagesList(dispatch, {
-                       softwareProductId,
-                       componentId,
-                       version
-               });
-               setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES, {softwareProductId, version, componentId, status});
-       },
-
-       navigateToVersionsPage(dispatch, {itemType, itemId, itemName, additionalProps, users}) {
-               PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers: users});
-               VersionsPageActionHelper.selectNone(dispatch);
-               VersionsPageActionHelper.fetchVersions(dispatch, {itemType, itemId}).then(() => {
-                       ItemsHelper.fetchItem(itemId).then(result => {
-                               setCurrentScreen(dispatch, enums.SCREEN.VERSIONS_PAGE, {status: result.status, itemType, itemId, itemName, additionalProps});
-                       });
-                       
-               });
-               
-       },
-
-       checkMergeStatus(dispatch, {itemId, versionId, version}) {
-               return ItemsHelper.fetchVersion({itemId, versionId}).then(response => {
-                       let state = response && response.state || {};
-                       let {synchronizationState} = state;
-                       // let inMerge = synchronizationState === SyncStates.MERGE;
-                       MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(data => {
-                               dispatch({
-                                       type: actionTypes.CHECK_MERGE_STATUS,
-                                       synchronizationState,
-                                       conflictInfoList: data.conflictInfoList
-                               });
-                       });
-               });
-       },
-
-       forceBreadCrumbsUpdate(dispatch) {
-               dispatch({
-                       type: actionTypes.SET_CURRENT_SCREEN,
-                       currentScreen: {
-                               forceBreadCrumbsUpdate: true
-                       }
-               });
-       },
-
-       updateCurrentScreenVersion(dispatch, version) {
-               dispatch({
-                       type: actionTypes.SET_CURRENT_SCREEN_VERSION,
-                       version
-               });
-       }
+    loadItemsLists(dispatch) {
+        LicenseModelActionHelper.fetchLicenseModels(dispatch);
+        LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
+        LicenseModelActionHelper.fetchArchivedLicenseModels(dispatch);
+        SoftwareProductActionHelper.fetchSoftwareProductList(dispatch);
+        SoftwareProductActionHelper.fetchFinalizedSoftwareProductList(dispatch);
+        SoftwareProductActionHelper.fetchArchivedSoftwareProductList(dispatch);
+    },
+
+    navigateToOnboardingCatalog(dispatch) {
+        UsersActionHelper.fetchUsersList(dispatch);
+        this.loadItemsLists(dispatch);
+        OnboardActionHelper.resetOnboardStore(dispatch);
+        setCurrentScreen(dispatch, enums.SCREEN.ONBOARDING_CATALOG);
+    },
+
+    autoSaveBeforeNavigate(
+        dispatch,
+        { softwareProductId, version, vspComponentId, dataToSave }
+    ) {
+        if (softwareProductId) {
+            if (vspComponentId) {
+                return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        version,
+                        vspComponentId,
+                        componentData: dataToSave.componentData,
+                        qdata: dataToSave.qdata
+                    }
+                );
+            }
+            return SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
+                softwareProduct: dataToSave.softwareProduct,
+                version,
+                qdata: dataToSave.qdata
+            });
+        }
+        return Promise.resolve();
+    },
+
+    navigateToLicenseModelOverview(
+        dispatch,
+        { licenseModelId, version, status }
+    ) {
+        /**
+         * TODO change to specific rest
+         */
+
+        LicenseModelActionHelper.fetchLicenseModelById(dispatch, {
+            licenseModelId,
+            version
+        }).then(() => {
+            LicenseModelActionHelper.fetchLicenseModelItems(dispatch, {
+                licenseModelId,
+                version
+            }).then(() => {
+                setCurrentScreen(
+                    dispatch,
+                    enums.SCREEN.LICENSE_MODEL_OVERVIEW,
+                    { licenseModelId, version, status }
+                );
+            });
+            licenseModelOverviewActionHelper.selectVLMListView(dispatch, {
+                buttonTab: null
+            });
+        });
+    },
+    navigateToLicenseAgreements(dispatch, { licenseModelId, version, status }) {
+        LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
+            licenseModelId,
+            version
+        });
+        LicenseModelActionHelper.fetchLicenseModelById(dispatch, {
+            licenseModelId,
+            version
+        }).then(() => {
+            setCurrentScreen(dispatch, enums.SCREEN.LICENSE_AGREEMENTS, {
+                licenseModelId,
+                version,
+                status
+            });
+        });
+    },
+
+    navigateToFeatureGroups(dispatch, { licenseModelId, version, status }) {
+        FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+            licenseModelId,
+            version
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.FEATURE_GROUPS, {
+            licenseModelId,
+            version,
+            status
+        });
+    },
+
+    navigateToEntitlementPools(dispatch, { licenseModelId, version, status }) {
+        EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {
+            licenseModelId,
+            version
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.ENTITLEMENT_POOLS, {
+            licenseModelId,
+            version,
+            status
+        });
+    },
+
+    navigateToLicenseKeyGroups(dispatch, { licenseModelId, version, status }) {
+        LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {
+            licenseModelId,
+            version
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.LICENSE_KEY_GROUPS, {
+            licenseModelId,
+            version,
+            status
+        });
+    },
+
+    navigateToLicenseModelActivityLog(
+        dispatch,
+        { licenseModelId, version, status }
+    ) {
+        ActivityLogActionHelper.fetchActivityLog(dispatch, {
+            itemId: licenseModelId,
+            versionId: version.id
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.ACTIVITY_LOG, {
+            licenseModelId,
+            version,
+            status
+        });
+    },
+
+    navigateToSoftwareProductLandingPage(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.clearComponentsStore(dispatch);
+        SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
+            softwareProductId,
+            version
+        }).then(response => {
+            let { vendorId: licenseModelId, licensingVersion } = response[0];
+            SoftwareProductActionHelper.loadSoftwareProductDetailsData(
+                dispatch,
+                { licenseModelId, licensingVersion }
+            );
+            SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+                dispatch,
+                { softwareProductId, version: version }
+            );
+            if (response[0].onboardingOrigin === onboardingOriginTypes.ZIP) {
+                SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(
+                    dispatch,
+                    { softwareProductId, version: version }
+                );
+            }
+            setCurrentScreen(
+                dispatch,
+                enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                { softwareProductId, licenseModelId, version, status }
+            );
+        });
+    },
+
+    navigateToSoftwareProductDetails(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
+            softwareProductId,
+            version
+        }).then(response => {
+            let { vendorId: licenseModelId, licensingVersion } = response[0];
+            SoftwareProductActionHelper.loadLicensingVersionsList(dispatch, {
+                licenseModelId
+            });
+            SoftwareProductActionHelper.loadSoftwareProductDetailsData(
+                dispatch,
+                { licenseModelId, licensingVersion }
+            );
+            setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, {
+                softwareProductId,
+                version,
+                status
+            });
+        });
+    },
+
+    navigateToSoftwareProductAttachmentsSetupTab(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {
+            softwareProductId,
+            version
+        });
+        SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {
+            activeTab: attachmentsTabsMapping.SETUP
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+    navigateToSoftwareProductAttachmentsValidationTab(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductActionHelper.processAndValidateHeatCandidate(dispatch, {
+            softwareProductId,
+            version
+        }).then(() => {
+            SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {
+                activeTab: attachmentsTabsMapping.VALIDATION
+            });
+            setCurrentScreen(
+                dispatch,
+                enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS,
+                { softwareProductId, version, status }
+            );
+        });
+    },
+
+    navigateToSoftwareProductProcesses(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        if (softwareProductId) {
+            SoftwareProductProcessesActionHelper.fetchProcessesList(dispatch, {
+                softwareProductId,
+                version
+            });
+        }
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+
+    navigateToSoftwareProductNetworks(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        if (softwareProductId) {
+            SoftwareProductNetworksActionHelper.fetchNetworksList(dispatch, {
+                softwareProductId,
+                version
+            });
+        }
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+
+    navigateToSoftwareProductDependencies(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+            dispatch,
+            { softwareProductId, version }
+        ).then(result => {
+            if (result.listCount >= 2) {
+                SoftwareProductDependenciesActionHelper.fetchDependencies(
+                    dispatch,
+                    { softwareProductId, version }
+                );
+                setCurrentScreen(
+                    dispatch,
+                    enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES,
+                    { softwareProductId, version, status }
+                );
+            } else {
+                this.navigateToSoftwareProductLandingPage(dispatch, {
+                    softwareProductId,
+                    version,
+                    status
+                });
+            }
+        });
+    },
+
+    navigateToSoftwareProductComponents(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+            dispatch,
+            { softwareProductId, version }
+        );
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+    navigateToSoftwareProductDeployment(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(
+            dispatch,
+            { softwareProductId, version }
+        );
+        ComputeFlavorActionHelper.fetchComputesListForVSP(dispatch, {
+            softwareProductId,
+            version
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+    navigateToSoftwareProductActivityLog(
+        dispatch,
+        { softwareProductId, version, status }
+    ) {
+        ActivityLogActionHelper.fetchActivityLog(dispatch, {
+            itemId: softwareProductId,
+            versionId: version.id
+        });
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG, {
+            softwareProductId,
+            version,
+            status
+        });
+    },
+
+    navigateToSoftwareProductComponentProcesses(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        if (componentId && softwareProductId) {
+            SoftwareProductComponentProcessesActionHelper.fetchProcessesList(
+                dispatch,
+                { componentId, softwareProductId, version }
+            );
+        }
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
+            { softwareProductId, componentId, version, status }
+        );
+    },
+
+    navigateToSoftwareProductComponentMonitoring(
+        dispatch,
+        { softwareProductId, version, componentId, status }
+    ) {
+        if (componentId && softwareProductId && version) {
+            SoftwareProductComponentsMonitoringAction.fetchExistingFiles(
+                dispatch,
+                { componentId, softwareProductId, version }
+            );
+        }
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING,
+            { softwareProductId, componentId, version, status }
+        );
+    },
+
+    navigateToComponentStorage(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(
+            dispatch,
+            { softwareProductId, vspComponentId: componentId, version }
+        );
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToComponentCompute(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(
+            dispatch,
+            { softwareProductId, vspComponentId: componentId, version }
+        );
+        if (componentId && softwareProductId) {
+            ComputeFlavorActionHelper.fetchComputesList(dispatch, {
+                softwareProductId,
+                componentId,
+                version
+            });
+        }
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToComponentNetwork(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        SoftwareProductComponentsNetworkActionHelper.fetchNICsList(dispatch, {
+            softwareProductId,
+            componentId,
+            version
+        });
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToSoftwareProductComponentGeneral(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        if (componentId && softwareProductId) {
+            SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(
+                dispatch,
+                { softwareProductId, vspComponentId: componentId, version }
+            );
+        }
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        this.navigateToSoftwareProductComponentGeneral(dispatch, {
+            softwareProductId,
+            componentId,
+            version,
+            status
+        });
+        dispatch({
+            type: SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
+            mapOfExpandedIds: {
+                [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: true,
+                [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS +
+                '|' +
+                componentId]: true
+            }
+        });
+    },
+
+    navigateToComponentLoadBalancing(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(
+            dispatch,
+            { softwareProductId, vspComponentId: componentId, version }
+        );
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToComponentImages(
+        dispatch,
+        { softwareProductId, componentId, version, status }
+    ) {
+        SoftwareProductComponentsImageActionHelper.fetchImagesList(dispatch, {
+            softwareProductId,
+            componentId,
+            version
+        });
+        setCurrentScreen(
+            dispatch,
+            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES,
+            { softwareProductId, version, componentId, status }
+        );
+    },
+
+    navigateToVersionsPage(
+        dispatch,
+        { itemType, itemId, itemName, additionalProps, users }
+    ) {
+        PermissionsActionHelper.fetchItemUsers(dispatch, {
+            itemId,
+            allUsers: users
+        });
+        VersionsPageActionHelper.selectNone(dispatch);
+        VersionsPageActionHelper.fetchVersions(dispatch, {
+            itemType,
+            itemId
+        }).then(() => {
+            ItemsHelper.fetchItem(itemId).then(result => {
+                setCurrentScreen(dispatch, enums.SCREEN.VERSIONS_PAGE, {
+                    status: result.status,
+                    itemType,
+                    itemId,
+                    itemName,
+                    additionalProps
+                });
+            });
+        });
+    },
+
+    checkMergeStatus(dispatch, { itemId, versionId, version }) {
+        return ItemsHelper.fetchVersion({ itemId, versionId }).then(
+            response => {
+                let state = (response && response.state) || {};
+                let { synchronizationState } = state;
+                // let inMerge = synchronizationState === SyncStates.MERGE;
+                MergeEditorActionHelper.fetchConflicts(dispatch, {
+                    itemId,
+                    version
+                }).then(data => {
+                    dispatch({
+                        type: actionTypes.CHECK_MERGE_STATUS,
+                        synchronizationState,
+                        conflictInfoList: data.conflictInfoList
+                    });
+                });
+            }
+        );
+    },
+
+    forceBreadCrumbsUpdate(dispatch) {
+        dispatch({
+            type: actionTypes.SET_CURRENT_SCREEN,
+            currentScreen: {
+                forceBreadCrumbsUpdate: true
+            }
+        });
+    },
+
+    updateCurrentScreenVersion(dispatch, version) {
+        dispatch({
+            type: actionTypes.SET_CURRENT_SCREEN_VERSION,
+            version
+        });
+    }
 };
 
 export default OnboardingActionHelper;
index 699fe9e..3605439 100644 (file)
@@ -18,83 +18,102 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
 export const DATE_FORMAT = 'MM/DD/YYYY';
 
 export const actionTypes = keyMirror({
-       SET_CURRENT_SCREEN: null,
-       SET_CURRENT_LICENSE_MODEL: null,
-       SET_CURRENT_SCREEN_VERSION: null,
-       UPDATE_CURRENT_SCREEN_PROPS: null,
-       UPDATE_ITEM_STATUS: null
+    SET_CURRENT_SCREEN: null,
+    SET_CURRENT_LICENSE_MODEL: null,
+    SET_CURRENT_SCREEN_VERSION: null,
+    UPDATE_CURRENT_SCREEN_PROPS: null,
+    UPDATE_ITEM_STATUS: null
 });
 
 export const screenTypes = keyMirror({
-       LICENSE_MODEL: null,
-       SOFTWARE_PRODUCT: null,
-       SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL: null
+    LICENSE_MODEL: null,
+    SOFTWARE_PRODUCT: null,
+    SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL: null
 });
 
 const breadcrumbsEnum = {
-       LICENSE_MODEL: 'LICENSE_MODEL',
-       VERSIONS_PAGE: 'VERSIONS_PAGE',
-       LICENSE_MODEL_OVERVIEW: 'LICENSE_MODEL_OVERVIEW',
-       LICENSE_AGREEMENTS: 'LICENSE_AGREEMENTS',
-       FEATURE_GROUPS: 'FEATURE_GROUPS',
-       ENTITLEMENT_POOLS: 'ENTITLEMENT_POOLS',
-       LICENSE_KEY_GROUPS: 'LICENSE_KEY_GROUPS',
-       ACTIVITY_LOG: 'ACTIVITY_LOG',
+    LICENSE_MODEL: 'LICENSE_MODEL',
+    VERSIONS_PAGE: 'VERSIONS_PAGE',
+    LICENSE_MODEL_OVERVIEW: 'LICENSE_MODEL_OVERVIEW',
+    LICENSE_AGREEMENTS: 'LICENSE_AGREEMENTS',
+    FEATURE_GROUPS: 'FEATURE_GROUPS',
+    ENTITLEMENT_POOLS: 'ENTITLEMENT_POOLS',
+    LICENSE_KEY_GROUPS: 'LICENSE_KEY_GROUPS',
+    ACTIVITY_LOG: 'ACTIVITY_LOG',
 
-       SOFTWARE_PRODUCT: 'SOFTWARE_PRODUCT',
-       SOFTWARE_PRODUCT_VERSIONS_PAGE: 'SOFTWARE_PRODUCT_VERSIONS_PAGE',
-       SOFTWARE_PRODUCT_LANDING_PAGE: 'SOFTWARE_PRODUCT_LANDING_PAGE',
-       SOFTWARE_PRODUCT_DETAILS: 'SOFTWARE_PRODUCT_DETAILS',
-       SOFTWARE_PRODUCT_ATTACHMENTS: 'SOFTWARE_PRODUCT_ATTACHMENTS',
-       SOFTWARE_PRODUCT_PROCESSES: 'SOFTWARE_PRODUCT_PROCESSES',
-       SOFTWARE_PRODUCT_DEPLOYMENT: 'SOFTWARE_PRODUCT_DEPLOYMENT',
-       SOFTWARE_PRODUCT_NETWORKS: 'SOFTWARE_PRODUCT_NETWORKS',
-       SOFTWARE_PRODUCT_DEPENDENCIES: 'SOFTWARE_PRODUCT_DEPENDENCIES',
-       SOFTWARE_PRODUCT_ACTIVITY_LOG: 'SOFTWARE_PRODUCT_ACTIVITY_LOG',
-       SOFTWARE_PRODUCT_COMPONENTS: 'SOFTWARE_PRODUCT_COMPONENTS',
-       SOFTWARE_PRODUCT_COMPONENT_PROCESSES: 'SOFTWARE_PRODUCT_COMPONENT_PROCESSES',
-       SOFTWARE_PRODUCT_COMPONENT_NETWORK: 'SOFTWARE_PRODUCT_COMPONENT_NETWORK',
-       SOFTWARE_PRODUCT_COMPONENT_STORAGE: 'SOFTWARE_PRODUCT_COMPONENT_STORAGE',
-       SOFTWARE_PRODUCT_COMPONENT_GENERAL: 'SOFTWARE_PRODUCT_COMPONENT_GENERAL',
-       SOFTWARE_PRODUCT_COMPONENT_COMPUTE: 'SOFTWARE_PRODUCT_COMPONENT_COMPUTE',
-       SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING: 'SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING',
-       SOFTWARE_PRODUCT_COMPONENT_MONITORING: 'SOFTWARE_PRODUCT_COMPONENT_MONITORING',
-       SOFTWARE_PRODUCT_COMPONENT_IMAGES: 'SOFTWARE_PRODUCT_COMPONENT_IMAGES'
+    SOFTWARE_PRODUCT: 'SOFTWARE_PRODUCT',
+    SOFTWARE_PRODUCT_VERSIONS_PAGE: 'SOFTWARE_PRODUCT_VERSIONS_PAGE',
+    SOFTWARE_PRODUCT_LANDING_PAGE: 'SOFTWARE_PRODUCT_LANDING_PAGE',
+    SOFTWARE_PRODUCT_DETAILS: 'SOFTWARE_PRODUCT_DETAILS',
+    SOFTWARE_PRODUCT_ATTACHMENTS: 'SOFTWARE_PRODUCT_ATTACHMENTS',
+    SOFTWARE_PRODUCT_PROCESSES: 'SOFTWARE_PRODUCT_PROCESSES',
+    SOFTWARE_PRODUCT_DEPLOYMENT: 'SOFTWARE_PRODUCT_DEPLOYMENT',
+    SOFTWARE_PRODUCT_NETWORKS: 'SOFTWARE_PRODUCT_NETWORKS',
+    SOFTWARE_PRODUCT_DEPENDENCIES: 'SOFTWARE_PRODUCT_DEPENDENCIES',
+    SOFTWARE_PRODUCT_ACTIVITY_LOG: 'SOFTWARE_PRODUCT_ACTIVITY_LOG',
+    SOFTWARE_PRODUCT_COMPONENTS: 'SOFTWARE_PRODUCT_COMPONENTS',
+    SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+        'SOFTWARE_PRODUCT_COMPONENT_PROCESSES',
+    SOFTWARE_PRODUCT_COMPONENT_NETWORK: 'SOFTWARE_PRODUCT_COMPONENT_NETWORK',
+    SOFTWARE_PRODUCT_COMPONENT_STORAGE: 'SOFTWARE_PRODUCT_COMPONENT_STORAGE',
+    SOFTWARE_PRODUCT_COMPONENT_GENERAL: 'SOFTWARE_PRODUCT_COMPONENT_GENERAL',
+    SOFTWARE_PRODUCT_COMPONENT_COMPUTE: 'SOFTWARE_PRODUCT_COMPONENT_COMPUTE',
+    SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+        'SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING',
+    SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+        'SOFTWARE_PRODUCT_COMPONENT_MONITORING',
+    SOFTWARE_PRODUCT_COMPONENT_IMAGES: 'SOFTWARE_PRODUCT_COMPONENT_IMAGES'
 };
 
 export const enums = keyMirror({
+    BREADCRUMS: { ...breadcrumbsEnum },
 
-       BREADCRUMS: {...breadcrumbsEnum},
+    SCREEN: {
+        ONBOARDING_CATALOG: 'ONBOARDING_CATALOG',
+        VERSIONS_PAGE: breadcrumbsEnum.VERSIONS_PAGE,
+        LICENSE_MODEL_OVERVIEW: breadcrumbsEnum.LICENSE_MODEL_OVERVIEW,
+        LICENSE_AGREEMENTS: breadcrumbsEnum.LICENSE_AGREEMENTS,
+        FEATURE_GROUPS: breadcrumbsEnum.FEATURE_GROUPS,
+        ENTITLEMENT_POOLS: breadcrumbsEnum.ENTITLEMENT_POOLS,
+        LICENSE_KEY_GROUPS: breadcrumbsEnum.LICENSE_KEY_GROUPS,
+        ACTIVITY_LOG: breadcrumbsEnum.ACTIVITY_LOG,
 
-       SCREEN: {
-               ONBOARDING_CATALOG: 'ONBOARDING_CATALOG',
-               VERSIONS_PAGE: breadcrumbsEnum.VERSIONS_PAGE,
-               LICENSE_MODEL_OVERVIEW: breadcrumbsEnum.LICENSE_MODEL_OVERVIEW,
-               LICENSE_AGREEMENTS: breadcrumbsEnum.LICENSE_AGREEMENTS,
-               FEATURE_GROUPS: breadcrumbsEnum.FEATURE_GROUPS,
-               ENTITLEMENT_POOLS: breadcrumbsEnum.ENTITLEMENT_POOLS,
-               LICENSE_KEY_GROUPS: breadcrumbsEnum.LICENSE_KEY_GROUPS,
-               ACTIVITY_LOG: breadcrumbsEnum.ACTIVITY_LOG,
-
-               SOFTWARE_PRODUCT_VERSIONS_PAGE: breadcrumbsEnum.SOFTWARE_PRODUCT_VERSIONS_PAGE,
-               SOFTWARE_PRODUCT_LANDING_PAGE: breadcrumbsEnum.SOFTWARE_PRODUCT_LANDING_PAGE,
-               SOFTWARE_PRODUCT_DETAILS: breadcrumbsEnum.SOFTWARE_PRODUCT_DETAILS,
-               SOFTWARE_PRODUCT_ATTACHMENTS: breadcrumbsEnum.SOFTWARE_PRODUCT_ATTACHMENTS,
-               SOFTWARE_PRODUCT_ATTACHMENTS_SETUP: 'SOFTWARE_PRODUCT_ATTACHMENTS_SETUP',
-               SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION: 'SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION',
-               SOFTWARE_PRODUCT_PROCESSES: breadcrumbsEnum.SOFTWARE_PRODUCT_PROCESSES,
-               SOFTWARE_PRODUCT_DEPLOYMENT: breadcrumbsEnum.SOFTWARE_PRODUCT_DEPLOYMENT,
-               SOFTWARE_PRODUCT_NETWORKS: breadcrumbsEnum.SOFTWARE_PRODUCT_NETWORKS,
-               SOFTWARE_PRODUCT_DEPENDENCIES: breadcrumbsEnum.SOFTWARE_PRODUCT_DEPENDENCIES,
-               SOFTWARE_PRODUCT_ACTIVITY_LOG: breadcrumbsEnum.SOFTWARE_PRODUCT_ACTIVITY_LOG,
-               SOFTWARE_PRODUCT_COMPONENTS: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENTS,
-               SOFTWARE_PRODUCT_COMPONENT_PROCESSES: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
-               SOFTWARE_PRODUCT_COMPONENT_COMPUTE: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
-               SOFTWARE_PRODUCT_COMPONENT_STORAGE: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
-               SOFTWARE_PRODUCT_COMPONENT_NETWORK: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
-               SOFTWARE_PRODUCT_COMPONENT_GENERAL: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
-               SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
-               SOFTWARE_PRODUCT_COMPONENT_MONITORING: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_MONITORING,
-               SOFTWARE_PRODUCT_COMPONENT_IMAGES: breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_IMAGES
-       }
+        SOFTWARE_PRODUCT_VERSIONS_PAGE:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_VERSIONS_PAGE,
+        SOFTWARE_PRODUCT_LANDING_PAGE:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_LANDING_PAGE,
+        SOFTWARE_PRODUCT_DETAILS: breadcrumbsEnum.SOFTWARE_PRODUCT_DETAILS,
+        SOFTWARE_PRODUCT_ATTACHMENTS:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_ATTACHMENTS,
+        SOFTWARE_PRODUCT_ATTACHMENTS_SETUP:
+            'SOFTWARE_PRODUCT_ATTACHMENTS_SETUP',
+        SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION:
+            'SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION',
+        SOFTWARE_PRODUCT_PROCESSES: breadcrumbsEnum.SOFTWARE_PRODUCT_PROCESSES,
+        SOFTWARE_PRODUCT_DEPLOYMENT:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_DEPLOYMENT,
+        SOFTWARE_PRODUCT_NETWORKS: breadcrumbsEnum.SOFTWARE_PRODUCT_NETWORKS,
+        SOFTWARE_PRODUCT_DEPENDENCIES:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_DEPENDENCIES,
+        SOFTWARE_PRODUCT_ACTIVITY_LOG:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_ACTIVITY_LOG,
+        SOFTWARE_PRODUCT_COMPONENTS:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENTS,
+        SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
+        SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
+        SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
+        SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
+        SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
+        SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
+        SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_MONITORING,
+        SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+            breadcrumbsEnum.SOFTWARE_PRODUCT_COMPONENT_IMAGES
+    }
 });
index e04f9b7..f462dd7 100644 (file)
@@ -16,7 +16,7 @@
 
 import React from 'react';
 
-import {render} from 'react-dom';
+import { render } from 'react-dom';
 import ReactDOM from 'react-dom';
 
 import isEqual from 'lodash/isEqual.js';
@@ -29,460 +29,812 @@ import store from 'sdc-app/AppStore.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 
+import {
+    onboardingMethod as onboardingMethodTypes,
+    onboardingOriginTypes
+} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
-import {onboardingMethod as onboardingMethodTypes, onboardingOriginTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { itemTypes } from './versionsPage/VersionsPageConstants.js';
 
-import {itemTypes} from './versionsPage/VersionsPageConstants.js';
-
-import {AppContainer} from 'react-hot-loader';
+import { AppContainer } from 'react-hot-loader';
 import HeatSetupActionHelper from './softwareProduct/attachments/setup/HeatSetupActionHelper.js';
 
-import {actionTypes, enums, screenTypes} from './OnboardingConstants.js';
+import { actionTypes, enums, screenTypes } from './OnboardingConstants.js';
 import OnboardingActionHelper from './OnboardingActionHelper.js';
 import Onboarding from './Onboarding.js';
 
 export default class OnboardingPunchOut {
-
-       render({options: {data, apiRoot, apiHeaders}, onEvent}, element) {
-               if (!this.unsubscribeFromStore) {
-                       this.unsubscribeFromStore = store.subscribe(() => this.handleStoreChange());
-               }
-
-               if (!this.isConfigSet) {
-                       Configuration.setCatalogApiRoot(apiRoot);
-                       Configuration.setCatalogApiHeaders(apiHeaders);
-                       this.isConfigSet = true;
-               }
-
-               this.onEvent = (...args) => onEvent(...args);
-               this.handleData(data);
-
-               if (!this.rendered) {
-                       render(
-                               <AppContainer>
-                                       <Application>
-                                               <Onboarding/>
-                                       </Application>
-                               </AppContainer>,
-                               element
-                       );
-                       if (module.hot) {
-                               module.hot.accept('sdc-app/onboarding/Onboarding.js', () => {
-                                       const NextOnboarding = require('sdc-app/onboarding/Onboarding.js').default;
-                                       render(
-                                               <AppContainer>
-                                                       <Application>
-                                                               <NextOnboarding/>
-                                                       </Application>
-                                               </AppContainer>,
-                                               element
-                                       );
-                               });
-                       }
-                       this.rendered = true;
-               }
-       }
-
-       unmount(element) {
-               ReactDOM.unmountComponentAtNode(element);
-               this.rendered = false;
-               this.unsubscribeFromStore();
-               this.unsubscribeFromStore = null;
-       }
-
-       handleData(data) {
-               let {breadcrumbs: {selectedKeys = []} = {}} = data;
-               let dispatch = action => store.dispatch(action);
-               let {currentScreen, users: {usersList}, softwareProductList, finalizedSoftwareProductList, licenseModelList, finalizedLicenseModelList,
-                       softwareProduct: {softwareProductEditor: {data: vspData = {}},
-                       softwareProductComponents = {}, softwareProductQuestionnaire = {}}, archivedLicenseModelList} = store.getState();
-               const wholeSoftwareProductList = [...softwareProductList, ...finalizedSoftwareProductList];
-               const wholeLicenseModelList = [...licenseModelList, ...finalizedLicenseModelList, ...archivedLicenseModelList];
-
-               let {props: {version, isReadOnlyMode}, screen} = currentScreen;
-               let {componentEditor: {data: componentData = {}, qdata: componentQData = {}}} = softwareProductComponents;
-               if (this.programmaticBreadcrumbsUpdate) {
-                       this.prevSelectedKeys = selectedKeys;
-                       this.programmaticBreadcrumbsUpdate = false;
-                       return;
-               }
-               if (!isEqual(selectedKeys, this.prevSelectedKeys)) {
-                       this.breadcrumbsPrefixSelected = isEqual(selectedKeys, this.prevSelectedKeys && this.prevSelectedKeys.slice(0, selectedKeys.length));
-
-                       const [, screenType, prevVspId, , prevComponentId] = this.prevSelectedKeys || [];
-                       let preNavigate = Promise.resolve();
-                       if(screenType === enums.BREADCRUMS.SOFTWARE_PRODUCT && screen !== 'VERSIONS_PAGE' && !isReadOnlyMode) {
-                               let dataToSave = prevVspId ? prevComponentId ? {componentData, qdata: componentQData} : {softwareProduct: vspData, qdata: softwareProductQuestionnaire.qdata} : {};
-                               preNavigate = OnboardingActionHelper.autoSaveBeforeNavigate(dispatch, {
-                                       softwareProductId: prevVspId,
-                                       version,
-                                       vspComponentId: prevComponentId,
-                                       dataToSave
-                               });
-                       }
-
-                       let {currentScreen: {props: {softwareProductId}}, softwareProduct: {softwareProductAttachments: {heatSetup, heatSetupCache}}} = store.getState();
-                       let heatSetupPopupPromise = currentScreen.screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS ?
-                               HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) :
-                               Promise.resolve();
-                       Promise.all([preNavigate, heatSetupPopupPromise]).then(() => {
-                               this.prevSelectedKeys = selectedKeys;
-                               if (selectedKeys.length === 0) {
-                                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.ONBOARDING_CATALOG});
-
-                               } else if (selectedKeys.length === 1 || selectedKeys[1] === enums.BREADCRUMS.LICENSE_MODEL) {
-                                       let [licenseModelId, , licenseModelScreen] = selectedKeys;
-                                       let licenseModel = wholeLicenseModelList.find(vlm => vlm.id === licenseModelId);
-                                       ScreensHelper.loadScreen(dispatch, {screen: licenseModelScreen, screenType: screenTypes.LICENSE_MODEL,
-                                               props: {licenseModelId, version, licenseModel, usersList}});
-
-                               } else if (selectedKeys.length <= 4 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT) {
-                                       let [licenseModelId, , softwareProductId, softwareProductScreen] = selectedKeys;
-                                       let softwareProduct = softwareProductId ?
-                                               wholeSoftwareProductList.find(({id}) => id === softwareProductId) :
-                                               wholeSoftwareProductList.find(({vendorId}) => vendorId === licenseModelId);
-                                       if (!softwareProductId) {
-                                               softwareProductId = softwareProduct.id;
-                                       }
-                                       if (softwareProductScreen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS) {
-                                               softwareProduct = vspData;
-                                               //check current vsp fields to determine which file has uploaded
-                                               if(vspData.onboardingOrigin === onboardingOriginTypes.ZIP || vspData.candidateOnboardingOrigin === onboardingOriginTypes.ZIP) {
-                                                       softwareProductScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP;
-                                               }
-                                               else if(vspData.onboardingOrigin === onboardingOriginTypes.CSAR) {
-                                                       softwareProductScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION;
-                                               }
-                                       }
-
-                                       ScreensHelper.loadScreen(dispatch, {screen: softwareProductScreen, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, softwareProduct, version, usersList}});
-
-                               } else if (selectedKeys.length === 5 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
-                                       let [licenseModelId, , softwareProductId, , componentId] = selectedKeys;
-                                       let softwareProduct = softwareProductId ?
-                                               wholeSoftwareProductList.find(({id}) => id === softwareProductId) :
-                                               wholeSoftwareProductList.find(({vendorId}) => vendorId === licenseModelId);
-                                       if (!softwareProductId) {
-                                               softwareProductId = softwareProduct.id;
-                                       }
-                                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, softwareProduct, componentId, version, usersList}});
-
-                               } else if (selectedKeys.length === 6 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
-                                       let [licenseModelId, , softwareProductId, , componentId, componentScreen] = selectedKeys;
-                                       let softwareProduct = softwareProductId ?
-                                               wholeSoftwareProductList.find(({id}) => id === softwareProductId) :
-                                               wholeSoftwareProductList.find(({vendorId}) => vendorId === licenseModelId);
-                                       if (!softwareProductId) {
-                                               softwareProductId = softwareProduct.id;
-                                       }
-                                       ScreensHelper.loadScreen(dispatch, {screen: componentScreen, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, softwareProduct, componentId, version, usersList}});
-
-                               } else {
-                                       console.error('Unknown breadcrumbs path: ', selectedKeys);
-                               }
-                       }).catch(() => {
-                               store.dispatch({
-                                       type: actionTypes.SET_CURRENT_SCREEN,
-                                       currentScreen: {
-                                               ...currentScreen,
-                                               forceBreadCrumbsUpdate: true
-                                       }
-                               });
-                       });
-               }
-       }
-
-       handleStoreChange() {
-               let {currentScreen, licenseModelList, finalizedLicenseModelList, softwareProductList, finalizedSoftwareProductList, versionsPage:
-                       {versionsList: {itemType, itemId}},
-                       softwareProduct: {softwareProductEditor: {data: currentSoftwareProduct = {onboardingMethod: ''}},
-                               softwareProductComponents: {componentsList}}, archivedLicenseModelList, archivedSoftwareProductList} = store.getState();
-               const wholeSoftwareProductList = lodashUnionBy(softwareProductList, [...finalizedSoftwareProductList, ...archivedSoftwareProductList], 'id');
-               const wholeLicenseModelList = lodashUnionBy(licenseModelList, [...finalizedLicenseModelList, ...archivedLicenseModelList], 'id');
-               let breadcrumbsData = {itemType, itemId, currentScreen, wholeLicenseModelList, wholeSoftwareProductList, currentSoftwareProduct, componentsList};
-
-               if (currentScreen.forceBreadCrumbsUpdate || !isEqual(breadcrumbsData, this.prevBreadcrumbsData) || this.breadcrumbsPrefixSelected) {
-                       this.prevBreadcrumbsData = breadcrumbsData;
-                       this.breadcrumbsPrefixSelected = false;
-                       this.programmaticBreadcrumbsUpdate = true;
-                       let breadcrumbs = this.buildBreadcrumbs(breadcrumbsData);
-                       this.onEvent('breadcrumbsupdated', breadcrumbs);
-                       store.dispatch({
-                               type: actionTypes.SET_CURRENT_SCREEN,
-                               currentScreen: {
-                                       ...currentScreen,
-                                       forceBreadCrumbsUpdate: false
-                               }
-                       });
-               }
-       }
-
-       buildBreadcrumbs({currentScreen: {screen, props}, itemType, itemId, currentSoftwareProduct,
-               wholeLicenseModelList, wholeSoftwareProductList, componentsList}) {
-               let {onboardingMethod, onboardingOrigin, candidateOnboardingOrigin} = currentSoftwareProduct;
-               let screenToBreadcrumb;
-               switch (screen) {
-                       case enums.SCREEN.ONBOARDING_CATALOG:
-                               return [];
-
-                       case enums.SCREEN.VERSIONS_PAGE:
-                               let firstMenuItems = itemType === itemTypes.LICENSE_MODEL ? [
-                                       {
-                                               selectedKey: itemId,
-                                               menuItems: wholeLicenseModelList.map(({id, name}) => ({
-                                                       key: id,
-                                                       displayText: name
-                                               }))
-                                       }] : [
-                                               {
-                                                       selectedKey: props.additionalProps.licenseModelId || currentSoftwareProduct.vendorId,
-                                                       menuItems: wholeLicenseModelList.map(({id, name}) => ({
-                                                               key: id,
-                                                               displayText: name
-                                                       }))
-                                               },
-                                               {
-                                                       selectedKey: enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                                       menuItems: [{
-                                                               key: enums.BREADCRUMS.LICENSE_MODEL,
-                                                               displayText: i18n('License Model')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                                               displayText: i18n('Software Products')
-                                                       }]
-                                               },
-                                               {
-                                                       selectedKey: itemId,
-                                                       menuItems: wholeSoftwareProductList
-                                                               .filter(({id, vendorId}) => vendorId === currentSoftwareProduct.vendorId || id === itemId)
-                                                               .map(({id, name}) => ({
-                                                                       key: id,
-                                                                       displayText: name
-                                                               }))
-                                               },
-                                       ];
-                               return [
-                                       ...firstMenuItems,
-                                       {
-                                               selectedKey: enums.BREADCRUMS.VERSIONS_PAGE,
-                                               menuItems: [{key: enums.BREADCRUMS.VERSIONS_PAGE, displayText: i18n('Versions Page')}]
-                                       }
-                               ];
-
-                       case enums.SCREEN.LICENSE_AGREEMENTS:
-                       case enums.SCREEN.FEATURE_GROUPS:
-                       case enums.SCREEN.ENTITLEMENT_POOLS:
-                       case enums.SCREEN.LICENSE_KEY_GROUPS:
-                       case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
-                       case enums.SCREEN.ACTIVITY_LOG:
-                               screenToBreadcrumb = {
-                                       [enums.SCREEN.LICENSE_AGREEMENTS]: enums.BREADCRUMS.LICENSE_AGREEMENTS,
-                                       [enums.SCREEN.FEATURE_GROUPS]: enums.BREADCRUMS.FEATURE_GROUPS,
-                                       [enums.SCREEN.ENTITLEMENT_POOLS]: enums.BREADCRUMS.ENTITLEMENT_POOLS,
-                                       [enums.SCREEN.LICENSE_KEY_GROUPS]: enums.BREADCRUMS.LICENSE_KEY_GROUPS,
-                                       [enums.SCREEN.LICENSE_MODEL_OVERVIEW]: enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
-                                       [enums.SCREEN.ACTIVITY_LOG]: enums.BREADCRUMS.ACTIVITY_LOG
-                               };
-                               return [
-                                       {
-                                               selectedKey: props.licenseModelId,
-                                               menuItems: wholeLicenseModelList.map(({id, name}) => ({
-                                                       key: id,
-                                                       displayText: name
-                                               }))
-                                       },
-                                       {
-                                               selectedKey: enums.BREADCRUMS.LICENSE_MODEL,
-                                               menuItems: [{
-                                                       key: enums.BREADCRUMS.LICENSE_MODEL,
-                                                       displayText: i18n('License Model')
-                                               },
-                                               ...(wholeSoftwareProductList.findIndex(({vendorId}) => vendorId === props.licenseModelId) === -1 ? [] : [{
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                                       displayText: i18n('Software Products')
-                                               }])]
-                                       }, {
-                                               selectedKey: screenToBreadcrumb[screen],
-                                               menuItems: [{
-                                                       key: enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
-                                                       displayText: i18n('Overview')
-                                               },{
-                                                       key: enums.BREADCRUMS.LICENSE_AGREEMENTS,
-                                                       displayText: i18n('License Agreements')
-                                               }, {
-                                                       key: enums.BREADCRUMS.FEATURE_GROUPS,
-                                                       displayText: i18n('Feature Groups')
-                                               }, {
-                                                       key: enums.BREADCRUMS.ENTITLEMENT_POOLS,
-                                                       displayText: i18n('Entitlement Pools')
-                                               }, {
-                                                       key: enums.BREADCRUMS.LICENSE_KEY_GROUPS,
-                                                       displayText: i18n('License Key Groups')
-                                               }, {
-                                                       key: enums.BREADCRUMS.ACTIVITY_LOG,
-                                                       displayText: i18n('Activity Log')
-                                               }]
-                                       }
-                               ];
-
-                       case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                               screenToBreadcrumb = {
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE]: enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_DETAILS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT]: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPLOYMENT,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG]: enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG
-                               };
-                               let componentScreenToBreadcrumb = {
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_IMAGES,
-                                       [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING
-                               };
-                               let licenseModelId = currentSoftwareProduct.vendorId;
-                               let returnedBreadcrumb = [
-                                       {
-                                               selectedKey: licenseModelId,
-                                               menuItems: wholeLicenseModelList.map(({id, name}) => ({
-                                                       key: id,
-                                                       displayText: name
-                                               }))
-                                       },
-                                       {
-                                               selectedKey: enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                               menuItems: [{
-                                                       key: enums.BREADCRUMS.LICENSE_MODEL,
-                                                       displayText: i18n('License Model')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                                       displayText: i18n('Software Products')
-                                               }]
-                                       },
-                                       {
-                                               selectedKey: props.softwareProductId,
-                                               menuItems: wholeSoftwareProductList
-                                                       .filter(({vendorId, id}) => vendorId === licenseModelId || id === props.softwareProductId)
-                                                       .map(({id, name}) => ({
-                                                               key: id,
-                                                               displayText: name
-                                                       }))
-                                       },
-                                       ...(/*screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE ? [] :*/ [{
-                                               selectedKey: screenToBreadcrumb[screen] || enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
-                                               menuItems: [{
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE,
-                                                       displayText: i18n('Overview')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS,
-                                                       displayText: i18n('General')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPLOYMENT,
-                                                       displayText: i18n('Deployment Flavors')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES,
-                                                       displayText: i18n('Process Details')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS,
-                                                       displayText: i18n('Networks')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES,
-                                                       displayText: i18n('Components Dependencies')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
-                                                       displayText: i18n('Attachments')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG,
-                                                       displayText: i18n('Activity Log')
-                                               }, {
-                                                       key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
-                                                       displayText: i18n('Components')
-                                               }].filter(item => {
-                                                       switch (item.key) {
-                                                               case enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS:
-                                                                       let isHeatData = onboardingOrigin !== onboardingOriginTypes.NONE || candidateOnboardingOrigin === onboardingOriginTypes.ZIP;
-                                                                       return isHeatData;
-                                                               case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS:
-                                                                       return (componentsList.length > 0);
-                                                               case enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPLOYMENT:
-                                                                       let isManualMode = onboardingMethod === onboardingMethodTypes.MANUAL;
-                                                                       return isManualMode;
-                                                               case enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES:
-                                                                       return (componentsList.length > 1);
-                                                               default:
-                                                                       return true;
-                                                       }
-                                               })
-                                       }])
-                               ];
-                               if(props.componentId) {
-                                       returnedBreadcrumb = [
-                                               ...returnedBreadcrumb, {
-                                                       selectedKey: props.componentId,
-                                                       menuItems: componentsList
-                                                               .map(({id, displayName}) => ({
-                                                                       key: id,
-                                                                       displayText: displayName
-                                                               }))
-                                               },
-                                               ...[{
-                                                       selectedKey: componentScreenToBreadcrumb[screen],
-                                                       menuItems: [{
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
-                                                               displayText: i18n('General')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
-                                                               displayText: i18n('Compute')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
-                                                               displayText: i18n('High Availability & Load Balancing')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
-                                                               displayText: i18n('Networks')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
-                                                               displayText: i18n('Storage')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_IMAGES,
-                                                               displayText: i18n('Images')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
-                                                               displayText: i18n('Process Details')
-                                                       }, {
-                                                               key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING,
-                                                               displayText: i18n('Monitoring')
-                                                       }]
-                                               }]
-                                       ];
-                               }
-                               return returnedBreadcrumb;
-               }
-       }
+    render({ options: { data, apiRoot, apiHeaders }, onEvent }, element) {
+        if (!this.unsubscribeFromStore) {
+            this.unsubscribeFromStore = store.subscribe(() =>
+                this.handleStoreChange()
+            );
+        }
+
+        if (!this.isConfigSet) {
+            Configuration.setCatalogApiRoot(apiRoot);
+            Configuration.setCatalogApiHeaders(apiHeaders);
+            this.isConfigSet = true;
+        }
+
+        this.onEvent = (...args) => onEvent(...args);
+        this.handleData(data);
+
+        if (!this.rendered) {
+            render(
+                <AppContainer>
+                    <Application>
+                        <Onboarding />
+                    </Application>
+                </AppContainer>,
+                element
+            );
+            if (module.hot) {
+                module.hot.accept('sdc-app/onboarding/Onboarding.js', () => {
+                    const NextOnboarding = require('sdc-app/onboarding/Onboarding.js')
+                        .default;
+                    render(
+                        <AppContainer>
+                            <Application>
+                                <NextOnboarding />
+                            </Application>
+                        </AppContainer>,
+                        element
+                    );
+                });
+            }
+            this.rendered = true;
+        }
+    }
+
+    unmount(element) {
+        ReactDOM.unmountComponentAtNode(element);
+        this.rendered = false;
+        this.unsubscribeFromStore();
+        this.unsubscribeFromStore = null;
+    }
+
+    handleData(data) {
+        let { breadcrumbs: { selectedKeys = [] } = {} } = data;
+        let dispatch = action => store.dispatch(action);
+        let {
+            currentScreen,
+            users: { usersList },
+            softwareProductList,
+            finalizedSoftwareProductList,
+            licenseModelList,
+            finalizedLicenseModelList,
+            softwareProduct: {
+                softwareProductEditor: { data: vspData = {} },
+                softwareProductComponents = {},
+                softwareProductQuestionnaire = {}
+            },
+            archivedLicenseModelList
+        } = store.getState();
+        const wholeSoftwareProductList = [
+            ...softwareProductList,
+            ...finalizedSoftwareProductList
+        ];
+        const wholeLicenseModelList = [
+            ...licenseModelList,
+            ...finalizedLicenseModelList,
+            ...archivedLicenseModelList
+        ];
+
+        let { props: { version, isReadOnlyMode }, screen } = currentScreen;
+        let {
+            componentEditor: {
+                data: componentData = {},
+                qdata: componentQData = {}
+            }
+        } = softwareProductComponents;
+        if (this.programmaticBreadcrumbsUpdate) {
+            this.prevSelectedKeys = selectedKeys;
+            this.programmaticBreadcrumbsUpdate = false;
+            return;
+        }
+        if (!isEqual(selectedKeys, this.prevSelectedKeys)) {
+            this.breadcrumbsPrefixSelected = isEqual(
+                selectedKeys,
+                this.prevSelectedKeys &&
+                    this.prevSelectedKeys.slice(0, selectedKeys.length)
+            );
+
+            const [, screenType, prevVspId, , prevComponentId] =
+                this.prevSelectedKeys || [];
+            let preNavigate = Promise.resolve();
+            if (
+                screenType === enums.BREADCRUMS.SOFTWARE_PRODUCT &&
+                screen !== 'VERSIONS_PAGE' &&
+                !isReadOnlyMode
+            ) {
+                let dataToSave = prevVspId
+                    ? prevComponentId
+                      ? { componentData, qdata: componentQData }
+                      : {
+                            softwareProduct: vspData,
+                            qdata: softwareProductQuestionnaire.qdata
+                        }
+                    : {};
+                preNavigate = OnboardingActionHelper.autoSaveBeforeNavigate(
+                    dispatch,
+                    {
+                        softwareProductId: prevVspId,
+                        version,
+                        vspComponentId: prevComponentId,
+                        dataToSave
+                    }
+                );
+            }
+
+            let {
+                currentScreen: { props: { softwareProductId } },
+                softwareProduct: {
+                    softwareProductAttachments: { heatSetup, heatSetupCache }
+                }
+            } = store.getState();
+            let heatSetupPopupPromise =
+                currentScreen.screen ===
+                enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
+                    ? HeatSetupActionHelper.heatSetupLeaveConfirmation(
+                          dispatch,
+                          { softwareProductId, heatSetup, heatSetupCache }
+                      )
+                    : Promise.resolve();
+            Promise.all([preNavigate, heatSetupPopupPromise])
+                .then(() => {
+                    this.prevSelectedKeys = selectedKeys;
+                    if (selectedKeys.length === 0) {
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: enums.SCREEN.ONBOARDING_CATALOG
+                        });
+                    } else if (
+                        selectedKeys.length === 1 ||
+                        selectedKeys[1] === enums.BREADCRUMS.LICENSE_MODEL
+                    ) {
+                        let [
+                            licenseModelId,
+                            ,
+                            licenseModelScreen
+                        ] = selectedKeys;
+                        let licenseModel = wholeLicenseModelList.find(
+                            vlm => vlm.id === licenseModelId
+                        );
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: licenseModelScreen,
+                            screenType: screenTypes.LICENSE_MODEL,
+                            props: {
+                                licenseModelId,
+                                version,
+                                licenseModel,
+                                usersList
+                            }
+                        });
+                    } else if (
+                        selectedKeys.length <= 4 &&
+                        selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT
+                    ) {
+                        let [
+                            licenseModelId,
+                            ,
+                            softwareProductId,
+                            softwareProductScreen
+                        ] = selectedKeys;
+                        let softwareProduct = softwareProductId
+                            ? wholeSoftwareProductList.find(
+                                  ({ id }) => id === softwareProductId
+                              )
+                            : wholeSoftwareProductList.find(
+                                  ({ vendorId }) => vendorId === licenseModelId
+                              );
+                        if (!softwareProductId) {
+                            softwareProductId = softwareProduct.id;
+                        }
+                        if (
+                            softwareProductScreen ===
+                            enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
+                        ) {
+                            softwareProduct = vspData;
+                            //check current vsp fields to determine which file has uploaded
+                            if (
+                                vspData.onboardingOrigin ===
+                                    onboardingOriginTypes.ZIP ||
+                                vspData.candidateOnboardingOrigin ===
+                                    onboardingOriginTypes.ZIP
+                            ) {
+                                softwareProductScreen =
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP;
+                            } else if (
+                                vspData.onboardingOrigin ===
+                                onboardingOriginTypes.CSAR
+                            ) {
+                                softwareProductScreen =
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION;
+                            }
+                        }
+
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: softwareProductScreen,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                softwareProduct,
+                                version,
+                                usersList
+                            }
+                        });
+                    } else if (
+                        selectedKeys.length === 5 &&
+                        selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT &&
+                        selectedKeys[3] ===
+                            enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS
+                    ) {
+                        let [
+                            licenseModelId,
+                            ,
+                            softwareProductId,
+                            ,
+                            componentId
+                        ] = selectedKeys;
+                        let softwareProduct = softwareProductId
+                            ? wholeSoftwareProductList.find(
+                                  ({ id }) => id === softwareProductId
+                              )
+                            : wholeSoftwareProductList.find(
+                                  ({ vendorId }) => vendorId === licenseModelId
+                              );
+                        if (!softwareProductId) {
+                            softwareProductId = softwareProduct.id;
+                        }
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                softwareProduct,
+                                componentId,
+                                version,
+                                usersList
+                            }
+                        });
+                    } else if (
+                        selectedKeys.length === 6 &&
+                        selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT &&
+                        selectedKeys[3] ===
+                            enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS
+                    ) {
+                        let [
+                            licenseModelId,
+                            ,
+                            softwareProductId,
+                            ,
+                            componentId,
+                            componentScreen
+                        ] = selectedKeys;
+                        let softwareProduct = softwareProductId
+                            ? wholeSoftwareProductList.find(
+                                  ({ id }) => id === softwareProductId
+                              )
+                            : wholeSoftwareProductList.find(
+                                  ({ vendorId }) => vendorId === licenseModelId
+                              );
+                        if (!softwareProductId) {
+                            softwareProductId = softwareProduct.id;
+                        }
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: componentScreen,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                softwareProduct,
+                                componentId,
+                                version,
+                                usersList
+                            }
+                        });
+                    } else {
+                        console.error(
+                            'Unknown breadcrumbs path: ',
+                            selectedKeys
+                        );
+                    }
+                })
+                .catch(() => {
+                    store.dispatch({
+                        type: actionTypes.SET_CURRENT_SCREEN,
+                        currentScreen: {
+                            ...currentScreen,
+                            forceBreadCrumbsUpdate: true
+                        }
+                    });
+                });
+        }
+    }
+
+    handleStoreChange() {
+        let {
+            currentScreen,
+            licenseModelList,
+            finalizedLicenseModelList,
+            softwareProductList,
+            finalizedSoftwareProductList,
+            versionsPage: { versionsList: { itemType, itemId } },
+            softwareProduct: {
+                softwareProductEditor: {
+                    data: currentSoftwareProduct = { onboardingMethod: '' }
+                },
+                softwareProductComponents: { componentsList }
+            },
+            archivedLicenseModelList,
+            archivedSoftwareProductList
+        } = store.getState();
+        const wholeSoftwareProductList = lodashUnionBy(
+            softwareProductList,
+            [...finalizedSoftwareProductList, ...archivedSoftwareProductList],
+            'id'
+        );
+        const wholeLicenseModelList = lodashUnionBy(
+            licenseModelList,
+            [...finalizedLicenseModelList, ...archivedLicenseModelList],
+            'id'
+        );
+        let breadcrumbsData = {
+            itemType,
+            itemId,
+            currentScreen,
+            wholeLicenseModelList,
+            wholeSoftwareProductList,
+            currentSoftwareProduct,
+            componentsList
+        };
+
+        if (
+            currentScreen.forceBreadCrumbsUpdate ||
+            !isEqual(breadcrumbsData, this.prevBreadcrumbsData) ||
+            this.breadcrumbsPrefixSelected
+        ) {
+            this.prevBreadcrumbsData = breadcrumbsData;
+            this.breadcrumbsPrefixSelected = false;
+            this.programmaticBreadcrumbsUpdate = true;
+            let breadcrumbs = this.buildBreadcrumbs(breadcrumbsData);
+            this.onEvent('breadcrumbsupdated', breadcrumbs);
+            store.dispatch({
+                type: actionTypes.SET_CURRENT_SCREEN,
+                currentScreen: {
+                    ...currentScreen,
+                    forceBreadCrumbsUpdate: false
+                }
+            });
+        }
+    }
+
+    buildBreadcrumbs({
+        currentScreen: { screen, props },
+        itemType,
+        itemId,
+        currentSoftwareProduct,
+        wholeLicenseModelList,
+        wholeSoftwareProductList,
+        componentsList
+    }) {
+        let {
+            onboardingMethod,
+            onboardingOrigin,
+            candidateOnboardingOrigin
+        } = currentSoftwareProduct;
+        let screenToBreadcrumb;
+        switch (screen) {
+            case enums.SCREEN.ONBOARDING_CATALOG:
+                return [];
+
+            case enums.SCREEN.VERSIONS_PAGE:
+                let firstMenuItems =
+                    itemType === itemTypes.LICENSE_MODEL
+                        ? [
+                              {
+                                  selectedKey: itemId,
+                                  menuItems: wholeLicenseModelList.map(
+                                      ({ id, name }) => ({
+                                          key: id,
+                                          displayText: name
+                                      })
+                                  )
+                              }
+                          ]
+                        : [
+                              {
+                                  selectedKey:
+                                      props.additionalProps.licenseModelId ||
+                                      currentSoftwareProduct.vendorId,
+                                  menuItems: wholeLicenseModelList.map(
+                                      ({ id, name }) => ({
+                                          key: id,
+                                          displayText: name
+                                      })
+                                  )
+                              },
+                              {
+                                  selectedKey:
+                                      enums.BREADCRUMS.SOFTWARE_PRODUCT,
+                                  menuItems: [
+                                      {
+                                          key: enums.BREADCRUMS.LICENSE_MODEL,
+                                          displayText: i18n('License Model')
+                                      },
+                                      {
+                                          key:
+                                              enums.BREADCRUMS.SOFTWARE_PRODUCT,
+                                          displayText: i18n('Software Products')
+                                      }
+                                  ]
+                              },
+                              {
+                                  selectedKey: itemId,
+                                  menuItems: wholeSoftwareProductList
+                                      .filter(
+                                          ({ id, vendorId }) =>
+                                              vendorId ===
+                                                  currentSoftwareProduct.vendorId ||
+                                              id === itemId
+                                      )
+                                      .map(({ id, name }) => ({
+                                          key: id,
+                                          displayText: name
+                                      }))
+                              }
+                          ];
+                return [
+                    ...firstMenuItems,
+                    {
+                        selectedKey: enums.BREADCRUMS.VERSIONS_PAGE,
+                        menuItems: [
+                            {
+                                key: enums.BREADCRUMS.VERSIONS_PAGE,
+                                displayText: i18n('Versions Page')
+                            }
+                        ]
+                    }
+                ];
+
+            case enums.SCREEN.LICENSE_AGREEMENTS:
+            case enums.SCREEN.FEATURE_GROUPS:
+            case enums.SCREEN.ENTITLEMENT_POOLS:
+            case enums.SCREEN.LICENSE_KEY_GROUPS:
+            case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+            case enums.SCREEN.ACTIVITY_LOG:
+                screenToBreadcrumb = {
+                    [enums.SCREEN.LICENSE_AGREEMENTS]:
+                        enums.BREADCRUMS.LICENSE_AGREEMENTS,
+                    [enums.SCREEN.FEATURE_GROUPS]:
+                        enums.BREADCRUMS.FEATURE_GROUPS,
+                    [enums.SCREEN.ENTITLEMENT_POOLS]:
+                        enums.BREADCRUMS.ENTITLEMENT_POOLS,
+                    [enums.SCREEN.LICENSE_KEY_GROUPS]:
+                        enums.BREADCRUMS.LICENSE_KEY_GROUPS,
+                    [enums.SCREEN.LICENSE_MODEL_OVERVIEW]:
+                        enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
+                    [enums.SCREEN.ACTIVITY_LOG]: enums.BREADCRUMS.ACTIVITY_LOG
+                };
+                return [
+                    {
+                        selectedKey: props.licenseModelId,
+                        menuItems: wholeLicenseModelList.map(
+                            ({ id, name }) => ({
+                                key: id,
+                                displayText: name
+                            })
+                        )
+                    },
+                    {
+                        selectedKey: enums.BREADCRUMS.LICENSE_MODEL,
+                        menuItems: [
+                            {
+                                key: enums.BREADCRUMS.LICENSE_MODEL,
+                                displayText: i18n('License Model')
+                            },
+                            ...(wholeSoftwareProductList.findIndex(
+                                ({ vendorId }) =>
+                                    vendorId === props.licenseModelId
+                            ) === -1
+                                ? []
+                                : [
+                                      {
+                                          key:
+                                              enums.BREADCRUMS.SOFTWARE_PRODUCT,
+                                          displayText: i18n('Software Products')
+                                      }
+                                  ])
+                        ]
+                    },
+                    {
+                        selectedKey: screenToBreadcrumb[screen],
+                        menuItems: [
+                            {
+                                key: enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
+                                displayText: i18n('Overview')
+                            },
+                            {
+                                key: enums.BREADCRUMS.LICENSE_AGREEMENTS,
+                                displayText: i18n('License Agreements')
+                            },
+                            {
+                                key: enums.BREADCRUMS.FEATURE_GROUPS,
+                                displayText: i18n('Feature Groups')
+                            },
+                            {
+                                key: enums.BREADCRUMS.ENTITLEMENT_POOLS,
+                                displayText: i18n('Entitlement Pools')
+                            },
+                            {
+                                key: enums.BREADCRUMS.LICENSE_KEY_GROUPS,
+                                displayText: i18n('License Key Groups')
+                            },
+                            {
+                                key: enums.BREADCRUMS.ACTIVITY_LOG,
+                                displayText: i18n('Activity Log')
+                            }
+                        ]
+                    }
+                ];
+
+            case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
+            case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
+            case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+                screenToBreadcrumb = {
+                    [enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_DETAILS]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPLOYMENT,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG
+                };
+                let componentScreenToBreadcrumb = {
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_STORAGE,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_NETWORK,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_GENERAL,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING]:
+                        enums.BREADCRUMS
+                            .SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_IMAGES,
+                    [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING]:
+                        enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING
+                };
+                let licenseModelId = currentSoftwareProduct.vendorId;
+                let returnedBreadcrumb = [
+                    {
+                        selectedKey: licenseModelId,
+                        menuItems: wholeLicenseModelList.map(
+                            ({ id, name }) => ({
+                                key: id,
+                                displayText: name
+                            })
+                        )
+                    },
+                    {
+                        selectedKey: enums.BREADCRUMS.SOFTWARE_PRODUCT,
+                        menuItems: [
+                            {
+                                key: enums.BREADCRUMS.LICENSE_MODEL,
+                                displayText: i18n('License Model')
+                            },
+                            {
+                                key: enums.BREADCRUMS.SOFTWARE_PRODUCT,
+                                displayText: i18n('Software Products')
+                            }
+                        ]
+                    },
+                    {
+                        selectedKey: props.softwareProductId,
+                        menuItems: wholeSoftwareProductList
+                            .filter(
+                                ({ vendorId, id }) =>
+                                    vendorId === licenseModelId ||
+                                    id === props.softwareProductId
+                            )
+                            .map(({ id, name }) => ({
+                                key: id,
+                                displayText: name
+                            }))
+                    },
+                    .../*screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE ? [] :*/ [
+                        {
+                            selectedKey:
+                                screenToBreadcrumb[screen] ||
+                                enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
+                            menuItems: [
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_LANDING_PAGE,
+                                    displayText: i18n('Overview')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_DETAILS,
+                                    displayText: i18n('General')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_DEPLOYMENT,
+                                    displayText: i18n('Deployment Flavors')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_PROCESSES,
+                                    displayText: i18n('Process Details')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_NETWORKS,
+                                    displayText: i18n('Networks')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_DEPENDENCIES,
+                                    displayText: i18n('Components Dependencies')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_ATTACHMENTS,
+                                    displayText: i18n('Attachments')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_ACTIVITY_LOG,
+                                    displayText: i18n('Activity Log')
+                                },
+                                {
+                                    key:
+                                        enums.BREADCRUMS
+                                            .SOFTWARE_PRODUCT_COMPONENTS,
+                                    displayText: i18n('Components')
+                                }
+                            ].filter(item => {
+                                switch (item.key) {
+                                    case enums.BREADCRUMS
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS:
+                                        let isHeatData =
+                                            onboardingOrigin !==
+                                                onboardingOriginTypes.NONE ||
+                                            candidateOnboardingOrigin ===
+                                                onboardingOriginTypes.ZIP;
+                                        return isHeatData;
+                                    case enums.BREADCRUMS
+                                        .SOFTWARE_PRODUCT_COMPONENTS:
+                                        return componentsList.length > 0;
+                                    case enums.BREADCRUMS
+                                        .SOFTWARE_PRODUCT_DEPLOYMENT:
+                                        let isManualMode =
+                                            onboardingMethod ===
+                                            onboardingMethodTypes.MANUAL;
+                                        return isManualMode;
+                                    case enums.BREADCRUMS
+                                        .SOFTWARE_PRODUCT_DEPENDENCIES:
+                                        return componentsList.length > 1;
+                                    default:
+                                        return true;
+                                }
+                            })
+                        }
+                    ]
+                ];
+                if (props.componentId) {
+                    returnedBreadcrumb = [
+                        ...returnedBreadcrumb,
+                        {
+                            selectedKey: props.componentId,
+                            menuItems: componentsList.map(
+                                ({ id, displayName }) => ({
+                                    key: id,
+                                    displayText: displayName
+                                })
+                            )
+                        },
+                        ...[
+                            {
+                                selectedKey:
+                                    componentScreenToBreadcrumb[screen],
+                                menuItems: [
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_GENERAL,
+                                        displayText: i18n('General')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_COMPUTE,
+                                        displayText: i18n('Compute')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING,
+                                        displayText: i18n(
+                                            'High Availability & Load Balancing'
+                                        )
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_NETWORK,
+                                        displayText: i18n('Networks')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_STORAGE,
+                                        displayText: i18n('Storage')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_IMAGES,
+                                        displayText: i18n('Images')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
+                                        displayText: i18n('Process Details')
+                                    },
+                                    {
+                                        key:
+                                            enums.BREADCRUMS
+                                                .SOFTWARE_PRODUCT_COMPONENT_MONITORING,
+                                        displayText: i18n('Monitoring')
+                                    }
+                                ]
+                            }
+                        ]
+                    ];
+                }
+                return returnedBreadcrumb;
+        }
+    }
 }
index 16c0e61..9abae2d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, enums} from './OnboardingConstants.js';
-import {actionTypes as permissionActionTypes} from './permissions/PermissionsConstants.js';
-import {actionTypes as licenseModelCreateActionTypes} from './licenseModel/creation/LicenseModelCreationConstants.js';
-import {actionTypes as softwareProductCreateActionTypes} from './softwareProduct/creation/SoftwareProductCreationConstants.js';
-import {actionTypes as versionCreateActionTypes} from './versionsPage/creation/VersionsPageCreationConstants.js';
-import {SyncStates} from 'sdc-app/common/merge/MergeEditorConstants.js';
-
-import {catalogItemStatuses} from './onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { actionTypes, enums } from './OnboardingConstants.js';
+import { actionTypes as permissionActionTypes } from './permissions/PermissionsConstants.js';
+import { actionTypes as licenseModelCreateActionTypes } from './licenseModel/creation/LicenseModelCreationConstants.js';
+import { actionTypes as softwareProductCreateActionTypes } from './softwareProduct/creation/SoftwareProductCreationConstants.js';
+import { actionTypes as versionCreateActionTypes } from './versionsPage/creation/VersionsPageCreationConstants.js';
+import { SyncStates } from 'sdc-app/common/merge/MergeEditorConstants.js';
+
+import { catalogItemStatuses } from './onboard/onboardingCatalog/OnboardingCatalogConstants.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 
-const checkReadOnly = ({isCollaborator = true, inMerge = false, isCertified = false, isArchived  = false}) => !isCollaborator || inMerge || isCertified || isArchived;
-
-const currentScreen = (state = {
-       forceBreadCrumbsUpdate: false,
-       screen: enums.SCREEN.ONBOARDING_CATALOG,
-       itemPermission: {},
-       props: {}
-}, action) => {
-
-       switch (action.type) {
-
-               case actionTypes.SET_CURRENT_SCREEN: {
-                       let itemPermission = {...state.itemPermission};
-                       let {currentScreen} = action;
-                       itemPermission.isArchived = currentScreen.props.status === catalogItemStatuses.ARCHIVED;
-
-                       if (currentScreen.props.version) {
-                               let {status} = currentScreen.props.version;
-                               itemPermission.isCertified = itemPermission.isCertified && status === catalogItemStatuses.CERTIFIED;
-                       }
-
-                       let isReadOnlyMode = checkReadOnly(itemPermission);
-                       let props = {...currentScreen.props, isReadOnlyMode};
-
-                       return {
-                               ...state,
-                               ...currentScreen,
-                               itemPermission,
-                               props
-                       };
-               }
-
-               case actionTypes.UPDATE_CURRENT_SCREEN_PROPS:
-                       return {
-                               ...state,
-                               props: {
-                                       ...state.props,
-                                       ...action.props,
-                                       isReadOnlyMode: checkReadOnly(state.itemPermission)
-                               }
-                       };
-
-               case actionTypes.SET_CURRENT_SCREEN_VERSION:
-                       return {
-                               ...state,
-                               props: {
-                                       ...state.props,
-                                       version: action.version,
-                                       isReadOnlyMode: checkReadOnly({...state.itemPermission,itemStatus: state.props.status})
-                               }
-                       };
-
-               case licenseModelCreateActionTypes.LICENSE_MODEL_CREATED:
-               case softwareProductCreateActionTypes.SOFTWARE_PRODUCT_CREATED:
-               case versionCreateActionTypes.VERSION_CREATED:
-                       return {
-                               ...state,
-                               itemPermission: {
-                                       isCollaborator: true,
-                                       inMerge: false,
-                                       isCertified: false
-                               },
-                               props: {
-                                       ...state.props,
-                                       isReadOnlyMode: false
-                               }
-                       };
-
-               case permissionActionTypes.ITEM_USERS_LOADED: {
-                       let userId = Configuration.get('UserID');
-                       let isCollaborator = false;
-
-                       if (userId === action.owner.userId) {
-                               isCollaborator = true;
-                       } else {
-                               isCollaborator = action.contributors.reduce(
-                                       (foundUser, contributor) => foundUser || contributor.userId === userId, false
-                               );
-                       }
-
-                       let itemPermission = {...state.itemPermission, isCollaborator};
-                       let isReadOnlyMode = checkReadOnly(itemPermission);
-                       let props = {...state.props, isReadOnlyMode};
-
-                       return {
-                               ...state,
-                               itemPermission,
-                               props
-                       };
-               }
-
-               case actionTypes.UPDATE_ITEM_STATUS: {
-                       const {itemState: {synchronizationState, dirty}, itemStatus, updatedVersion, archivedStatus} = action;
-                       const inMerge = synchronizationState === SyncStates.MERGE;
-                       const isOutOfSync = synchronizationState === SyncStates.OUT_OF_SYNC;
-                       const isUpToDate = synchronizationState === SyncStates.UP_TO_DATE;
-                       const isCertified = itemStatus === catalogItemStatuses.CERTIFIED;
-                       const isArchived = archivedStatus === catalogItemStatuses.ARCHIVED;
-                       const itemPermission = {...state.itemPermission, inMerge, isDirty: dirty, isOutOfSync, isUpToDate, isCertified, isArchived};
-                       const isReadOnlyMode = checkReadOnly(itemPermission);
-                       const props = {...state.props, isReadOnlyMode, version: {...state.props.version, ...updatedVersion}};
-
-                       return {
-                               ...state,
-                               itemPermission,
-                               props
-                       };
-               }
-
-               default:
-                       return state;
-
-       }
-
+const checkReadOnly = ({
+    isCollaborator = true,
+    inMerge = false,
+    isCertified = false,
+    isArchived = false
+}) => !isCollaborator || inMerge || isCertified || isArchived;
+
+const currentScreen = (
+    state = {
+        forceBreadCrumbsUpdate: false,
+        screen: enums.SCREEN.ONBOARDING_CATALOG,
+        itemPermission: {},
+        props: {}
+    },
+    action
+) => {
+    switch (action.type) {
+        case actionTypes.SET_CURRENT_SCREEN: {
+            let itemPermission = { ...state.itemPermission };
+            let { currentScreen } = action;
+            itemPermission.isArchived =
+                currentScreen.props.status === catalogItemStatuses.ARCHIVED;
+
+            if (currentScreen.props.version) {
+                let { status } = currentScreen.props.version;
+                itemPermission.isCertified =
+                    itemPermission.isCertified &&
+                    status === catalogItemStatuses.CERTIFIED;
+            }
+
+            let isReadOnlyMode = checkReadOnly(itemPermission);
+            let props = { ...currentScreen.props, isReadOnlyMode };
+
+            return {
+                ...state,
+                ...currentScreen,
+                itemPermission,
+                props
+            };
+        }
+
+        case actionTypes.UPDATE_CURRENT_SCREEN_PROPS:
+            return {
+                ...state,
+                props: {
+                    ...state.props,
+                    ...action.props,
+                    isReadOnlyMode: checkReadOnly(state.itemPermission)
+                }
+            };
+
+        case actionTypes.SET_CURRENT_SCREEN_VERSION:
+            return {
+                ...state,
+                props: {
+                    ...state.props,
+                    version: action.version,
+                    isReadOnlyMode: checkReadOnly({
+                        ...state.itemPermission,
+                        itemStatus: state.props.status
+                    })
+                }
+            };
+
+        case licenseModelCreateActionTypes.LICENSE_MODEL_CREATED:
+        case softwareProductCreateActionTypes.SOFTWARE_PRODUCT_CREATED:
+        case versionCreateActionTypes.VERSION_CREATED:
+            return {
+                ...state,
+                itemPermission: {
+                    isCollaborator: true,
+                    inMerge: false,
+                    isCertified: false
+                },
+                props: {
+                    ...state.props,
+                    isReadOnlyMode: false
+                }
+            };
+
+        case permissionActionTypes.ITEM_USERS_LOADED: {
+            let userId = Configuration.get('UserID');
+            let isCollaborator = false;
+
+            if (userId === action.owner.userId) {
+                isCollaborator = true;
+            } else {
+                isCollaborator = action.contributors.reduce(
+                    (foundUser, contributor) =>
+                        foundUser || contributor.userId === userId,
+                    false
+                );
+            }
+
+            let itemPermission = { ...state.itemPermission, isCollaborator };
+            let isReadOnlyMode = checkReadOnly(itemPermission);
+            let props = { ...state.props, isReadOnlyMode };
+
+            return {
+                ...state,
+                itemPermission,
+                props
+            };
+        }
+
+        case actionTypes.UPDATE_ITEM_STATUS: {
+            const {
+                itemState: { synchronizationState, dirty },
+                itemStatus,
+                updatedVersion,
+                archivedStatus
+            } = action;
+            const inMerge = synchronizationState === SyncStates.MERGE;
+            const isOutOfSync = synchronizationState === SyncStates.OUT_OF_SYNC;
+            const isUpToDate = synchronizationState === SyncStates.UP_TO_DATE;
+            const isCertified = itemStatus === catalogItemStatuses.CERTIFIED;
+            const isArchived = archivedStatus === catalogItemStatuses.ARCHIVED;
+            const itemPermission = {
+                ...state.itemPermission,
+                inMerge,
+                isDirty: dirty,
+                isOutOfSync,
+                isUpToDate,
+                isCertified,
+                isArchived
+            };
+            const isReadOnlyMode = checkReadOnly(itemPermission);
+            const props = {
+                ...state.props,
+                isReadOnlyMode,
+                version: { ...state.props.version, ...updatedVersion }
+            };
+
+            return {
+                ...state,
+                itemPermission,
+                props
+            };
+        }
+
+        default:
+            return state;
+    }
 };
 
 export default currentScreen;
index 5b678b1..3b526a6 100644 (file)
@@ -30,19 +30,19 @@ import revisionsReducer from './revisions/RevisionsReducer.js';
 import featuresReducer from 'sdc-app/features/FeaturesReducer.js';
 
 export default {
-       currentScreen: currentScreenReducer,
-       licenseModel: licenseModelReducer,
-       licenseModelList: licenseModelListReducer,
-       archivedLicenseModelList: archivedLicenseModelListReducer,
-       archivedSoftwareProductList: archivedSoftwareProductListReducer,
-       finalizedLicenseModelList: finalizedLicenseModelListReducer,
-       finalizedSoftwareProductList: finalizedSoftwareProductReducer,
-       mergeEditor: mergeEditorReducer,
-       onboard: onboardReducer,
-       softwareProduct: softwareProductReducer,
-       softwareProductList: softwareProductListReducer,
-       users: usersReducer,
-       versionsPage: versionsPageReducer,
-       revisions: revisionsReducer,
-       features: featuresReducer
+    currentScreen: currentScreenReducer,
+    licenseModel: licenseModelReducer,
+    licenseModelList: licenseModelListReducer,
+    archivedLicenseModelList: archivedLicenseModelListReducer,
+    archivedSoftwareProductList: archivedSoftwareProductListReducer,
+    finalizedLicenseModelList: finalizedLicenseModelListReducer,
+    finalizedSoftwareProductList: finalizedSoftwareProductReducer,
+    mergeEditor: mergeEditorReducer,
+    onboard: onboardReducer,
+    softwareProduct: softwareProductReducer,
+    softwareProductList: softwareProductListReducer,
+    users: usersReducer,
+    versionsPage: versionsPageReducer,
+    revisions: revisionsReducer,
+    features: featuresReducer
 };
index 7877085..69e514b 100644 (file)
@@ -25,8 +25,8 @@ import FeatureGroupListEditor from './licenseModel/featureGroups/FeatureGroupLis
 import LicenseKeyGroupsListEditor from './licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js';
 import EntitlementPoolsListEditor from './licenseModel/entitlementPools/EntitlementPoolsListEditor.js';
 import SoftwareProduct from './softwareProduct/SoftwareProduct.js';
-import SoftwareProductLandingPage  from './softwareProduct/landingPage/SoftwareProductLandingPage.js';
-import SoftwareProductDetails  from './softwareProduct/details/SoftwareProductDetails.js';
+import SoftwareProductLandingPage from './softwareProduct/landingPage/SoftwareProductLandingPage.js';
+import SoftwareProductDetails from './softwareProduct/details/SoftwareProductDetails.js';
 import SoftwareProductAttachments from './softwareProduct/attachments/SoftwareProductAttachments.js';
 import SoftwareProductProcesses from './softwareProduct/processes/SoftwareProductProcesses.js';
 import SoftwareProductDeployment from './softwareProduct/deployment/SoftwareProductDeployment.js';
@@ -48,136 +48,243 @@ import PropTypes from 'prop-types';
 import React from 'react';
 
 import ReactDOM from 'react-dom';
-import {enums} from './OnboardingConstants.js';
+import { enums } from './OnboardingConstants.js';
 
 export default class OnboardingView extends React.Component {
-       static propTypes = {
-               currentScreen: PropTypes.shape({
-                       screen: PropTypes.oneOf(objectValues(enums.SCREEN)).isRequired,
-                       props: PropTypes.object.isRequired,
-                       itemPermission: PropTypes.object
-               }).isRequired
-       };
+    static propTypes = {
+        currentScreen: PropTypes.shape({
+            screen: PropTypes.oneOf(objectValues(enums.SCREEN)).isRequired,
+            props: PropTypes.object.isRequired,
+            itemPermission: PropTypes.object
+        }).isRequired
+    };
 
-       componentDidMount() {
-               let element = ReactDOM.findDOMNode(this);
-               element.addEventListener('click', event => {
-                       if (event.target.tagName === 'A') {
-                               event.preventDefault();
-                       }
-               });
-               ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
-                       element.addEventListener(eventType, event => event.stopPropagation())
-               );
-       }
+    componentDidMount() {
+        let element = ReactDOM.findDOMNode(this);
+        element.addEventListener('click', event => {
+            if (event.target.tagName === 'A') {
+                event.preventDefault();
+            }
+        });
+        ['wheel', 'mousewheel', 'DOMMouseScroll'].forEach(eventType =>
+            element.addEventListener(eventType, event =>
+                event.stopPropagation()
+            )
+        );
+    }
 
-       render() {
-               let {currentScreen} = this.props;
-               let {screen, props} = currentScreen;
+    render() {
+        let { currentScreen } = this.props;
+        let { screen, props } = currentScreen;
 
-               return (
-                       <div className='dox-ui dox-ui-punch-out dox-ui-punch-out-full-page'>
-                               {(() => {
-                                       switch (screen) {
-                                               case enums.SCREEN.ONBOARDING_CATALOG:
-                                                       return <Onboard {...props}/>;
-                                               case enums.SCREEN.VERSIONS_PAGE:
-                                                       return <VersionsPage {...props} />;
+        return (
+            <div className="dox-ui dox-ui-punch-out dox-ui-punch-out-full-page">
+                {(() => {
+                    switch (screen) {
+                        case enums.SCREEN.ONBOARDING_CATALOG:
+                            return <Onboard {...props} />;
+                        case enums.SCREEN.VERSIONS_PAGE:
+                            return <VersionsPage {...props} />;
 
-                                               case enums.SCREEN.LICENSE_AGREEMENTS:
-                                               case enums.SCREEN.FEATURE_GROUPS:
-                                               case enums.SCREEN.ENTITLEMENT_POOLS:
-                                               case enums.SCREEN.LICENSE_KEY_GROUPS:
-                                               case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
-                                               case enums.SCREEN.ACTIVITY_LOG:
-                                                       return (
-                                                               <LicenseModel currentScreen={currentScreen}>
-                                                                       {
-                                                                               (()=>{
-                                                                                       switch(screen) {
-                                                                                               case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
-                                                                                                       return <LicenseModelOverview {...props}/>;
-                                                                                               case enums.SCREEN.LICENSE_AGREEMENTS:
-                                                                                                       return <LicenseAgreementListEditor {...props}/>;
-                                                                                               case enums.SCREEN.FEATURE_GROUPS:
-                                                                                                       return <FeatureGroupListEditor {...props}/>;
-                                                                                               case enums.SCREEN.ENTITLEMENT_POOLS:
-                                                                                                       return <EntitlementPoolsListEditor {...props}/>;
-                                                                                               case enums.SCREEN.LICENSE_KEY_GROUPS:
-                                                                                                       return <LicenseKeyGroupsListEditor {...props}/>;
-                                                                                               case enums.SCREEN.ACTIVITY_LOG:
-                                                                                                       return <ActivityLog {...props}/>;
-                                                                                       }
-                                                                               })()
-                                                                       }
-                                                               </LicenseModel>
-                                                       );
+                        case enums.SCREEN.LICENSE_AGREEMENTS:
+                        case enums.SCREEN.FEATURE_GROUPS:
+                        case enums.SCREEN.ENTITLEMENT_POOLS:
+                        case enums.SCREEN.LICENSE_KEY_GROUPS:
+                        case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+                        case enums.SCREEN.ACTIVITY_LOG:
+                            return (
+                                <LicenseModel currentScreen={currentScreen}>
+                                    {(() => {
+                                        switch (screen) {
+                                            case enums.SCREEN
+                                                .LICENSE_MODEL_OVERVIEW:
+                                                return (
+                                                    <LicenseModelOverview
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .LICENSE_AGREEMENTS:
+                                                return (
+                                                    <LicenseAgreementListEditor
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN.FEATURE_GROUPS:
+                                                return (
+                                                    <FeatureGroupListEditor
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN.ENTITLEMENT_POOLS:
+                                                return (
+                                                    <EntitlementPoolsListEditor
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .LICENSE_KEY_GROUPS:
+                                                return (
+                                                    <LicenseKeyGroupsListEditor
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN.ACTIVITY_LOG:
+                                                return (
+                                                    <ActivityLog {...props} />
+                                                );
+                                        }
+                                    })()}
+                                </LicenseModel>
+                            );
 
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                                               case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-                                                       return (
-                                                               <SoftwareProduct currentScreen={currentScreen}>
-                                                                       {
-                                                                               (()=>{
-                                                                                       switch(screen) {
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-                                                                                                       return <SoftwareProductLandingPage {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                                                                                                       return <SoftwareProductDetails {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
-                                                                                                       return <SoftwareProductAttachments className='no-padding-content-area' {...props} />;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-                                                                                                       return <SoftwareProductProcesses {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-                                                                                                       return <SoftwareProductDeployment {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-                                                                                                       return <SoftwareProductNetworks {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-                                                                                                       return <SoftwareProductDependencies {...props} />;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-                                                                                                       return <SoftwareProductComponentsList  {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-                                                                                                       return <SoftwareProductComponentProcessesList  {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                                                                                                       return <SoftwareProductComponentStorage {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                                                                                                       return <SoftwareProductComponentsNetworkList {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                                                                                                       return <SoftwareProductComponentsGeneral{...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                                                                                                       return <SoftwareProductComponentsCompute {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                                                                                                       return <SoftwareProductComponentLoadBalancing{...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                                                                                                       return <SoftwareProductComponentsImageList{...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                                                                                                       return <SoftwareProductComponentsMonitoring {...props}/>;
-                                                                                               case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-                                                                                                       return <ActivityLog {...props}/>;
-                                                                                       }
-                                                                               })()
-                                                                       }
-                                                               </SoftwareProduct>
-                                                       );
-                                       }
-                               })()}
-                       </div>
-               );
-       }
+                        case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+                        case enums.SCREEN
+                            .SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+                        case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+                            return (
+                                <SoftwareProduct currentScreen={currentScreen}>
+                                    {(() => {
+                                        switch (screen) {
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_LANDING_PAGE:
+                                                return (
+                                                    <SoftwareProductLandingPage
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_DETAILS:
+                                                return (
+                                                    <SoftwareProductDetails
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_ATTACHMENTS:
+                                                return (
+                                                    <SoftwareProductAttachments
+                                                        className="no-padding-content-area"
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_PROCESSES:
+                                                return (
+                                                    <SoftwareProductProcesses
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_DEPLOYMENT:
+                                                return (
+                                                    <SoftwareProductDeployment
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_NETWORKS:
+                                                return (
+                                                    <SoftwareProductNetworks
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_DEPENDENCIES:
+                                                return (
+                                                    <SoftwareProductDependencies
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENTS:
+                                                return (
+                                                    <SoftwareProductComponentsList
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+                                                return (
+                                                    <SoftwareProductComponentProcessesList
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+                                                return (
+                                                    <SoftwareProductComponentStorage
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+                                                return (
+                                                    <SoftwareProductComponentsNetworkList
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+                                                return (
+                                                    <SoftwareProductComponentsGeneral
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+                                                return (
+                                                    <SoftwareProductComponentsCompute
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+                                                return (
+                                                    <SoftwareProductComponentLoadBalancing
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+                                                return (
+                                                    <SoftwareProductComponentsImageList
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+                                                return (
+                                                    <SoftwareProductComponentsMonitoring
+                                                        {...props}
+                                                    />
+                                                );
+                                            case enums.SCREEN
+                                                .SOFTWARE_PRODUCT_ACTIVITY_LOG:
+                                                return (
+                                                    <ActivityLog {...props} />
+                                                );
+                                        }
+                                    })()}
+                                </SoftwareProduct>
+                            );
+                    }
+                })()}
+            </div>
+        );
+    }
 }
-
index 8e4750e..d5563f4 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {actionTypes} from './LicenseModelConstants.js';
+import { actionTypes } from './LicenseModelConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.ARCHIVED_LICENSE_MODELS_LIST_LOADED:
-                       return [...action.response.results];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.ARCHIVED_LICENSE_MODELS_LIST_LOADED:
+            return [...action.response.results];
+        default:
+            return state;
+    }
 };
index cc9d9c5..b5c2bff 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './LicenseModelConstants.js';
+import { actionTypes } from './LicenseModelConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED:
-                       return [...action.response.results];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED:
+            return [...action.response.results];
+        default:
+            return state;
+    }
 };
index c390ecc..cea369d 100644 (file)
  * 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 { connect } from 'react-redux';
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 import PermissionsActionHelper from './../permissions/PermissionsActionHelper.js';
 import RevisionsActionHelper from './../revisions/RevisionsActionHelper.js';
 
 import LicenseModelActionHelper from './LicenseModelActionHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
 
 const buildNavigationBarProps = (licenseModel, screen) => {
-       const {id, vendorName, version} = licenseModel;
-       const meta = {version};
-
-       const groups = [{
-               id,
-               name: vendorName,
-               items: [
-                       {
-                               id: enums.SCREEN.LICENSE_MODEL_OVERVIEW,
-                               name: i18n('Overview'),
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.LICENSE_AGREEMENTS,
-                               name: i18n('License Agreements'),
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.FEATURE_GROUPS,
-                               name: i18n('Feature Groups'),
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.ENTITLEMENT_POOLS,
-                               name: i18n('Entitlement Pools'),
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.LICENSE_KEY_GROUPS,
-                               name: i18n('License Key Groups'),
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.ACTIVITY_LOG,
-                               name: i18n('Activity Log'),
-                               meta
-                       }
-               ]
-       }];
-
-       return {
-               activeItemId: screen, groups
-       };
+    const { id, vendorName, version } = licenseModel;
+    const meta = { version };
+
+    const groups = [
+        {
+            id,
+            name: vendorName,
+            items: [
+                {
+                    id: enums.SCREEN.LICENSE_MODEL_OVERVIEW,
+                    name: i18n('Overview'),
+                    meta
+                },
+                {
+                    id: enums.SCREEN.LICENSE_AGREEMENTS,
+                    name: i18n('License Agreements'),
+                    meta
+                },
+                {
+                    id: enums.SCREEN.FEATURE_GROUPS,
+                    name: i18n('Feature Groups'),
+                    meta
+                },
+                {
+                    id: enums.SCREEN.ENTITLEMENT_POOLS,
+                    name: i18n('Entitlement Pools'),
+                    meta
+                },
+                {
+                    id: enums.SCREEN.LICENSE_KEY_GROUPS,
+                    name: i18n('License Key Groups'),
+                    meta
+                },
+                {
+                    id: enums.SCREEN.ACTIVITY_LOG,
+                    name: i18n('Activity Log'),
+                    meta
+                }
+            ]
+        }
+    ];
+
+    return {
+        activeItemId: screen,
+        groups
+    };
 };
 
-
 const buildVersionControllerProps = ({
-       licenseModelEditor = {data: {}},
-       versions,
-       currentVersion,
-       userInfo,
-       usersList,
-       permissions,
-       isArchived,
-       itemPermission,
-       isReadOnlyMode
+    licenseModelEditor = { data: {} },
+    versions,
+    currentVersion,
+    userInfo,
+    usersList,
+    permissions,
+    isArchived,
+    itemPermission,
+    isReadOnlyMode
 }) => {
-       const {isValidityData = true} = licenseModelEditor;
-       return {
-               version: currentVersion,
-               viewableVersions: versions,
-               isFormDataValid: isValidityData,
-               permissions,
-               userInfo,
-               usersList,
-               isArchived,
-               itemName: licenseModelEditor.data.vendorName,
-               itemPermission,
-               isReadOnlyMode
-       };
+    const { isValidityData = true } = licenseModelEditor;
+    return {
+        version: currentVersion,
+        viewableVersions: versions,
+        isFormDataValid: isValidityData,
+        permissions,
+        userInfo,
+        usersList,
+        isArchived,
+        itemName: licenseModelEditor.data.vendorName,
+        itemPermission,
+        isReadOnlyMode
+    };
 };
 
-
-const mapStateToProps = ({
-       users: {userInfo, usersList},
-       licenseModel: {licenseModelEditor},
-       versionsPage: {permissions, versionsList: {versions, itemName}}
-}, {
-       currentScreen: {screen, itemPermission, props: {isReadOnlyMode, version: currentVersion}}
-}) => {
-       return {
-               versionControllerProps: buildVersionControllerProps({
-                       licenseModelEditor,
-                       versions,
-                       currentVersion,
-                       userInfo,
-                       permissions,
-                       usersList,
-                       isArchived: itemPermission.isArchived,
-                       itemPermission,
-                       isReadOnlyMode
-               }),
-               navigationBarProps: buildNavigationBarProps(licenseModelEditor.data, screen)
-       };
+const mapStateToProps = (
+    {
+        users: { userInfo, usersList },
+        licenseModel: { licenseModelEditor },
+        versionsPage: { permissions, versionsList: { versions } }
+    },
+    {
+        currentScreen: {
+            screen,
+            itemPermission,
+            props: { isReadOnlyMode, version: currentVersion }
+        }
+    }
+) => {
+    return {
+        versionControllerProps: buildVersionControllerProps({
+            licenseModelEditor,
+            versions,
+            currentVersion,
+            userInfo,
+            permissions,
+            usersList,
+            isArchived: itemPermission.isArchived,
+            itemPermission,
+            isReadOnlyMode
+        }),
+        navigationBarProps: buildNavigationBarProps(
+            licenseModelEditor.data,
+            screen
+        )
+    };
 };
 
-
-const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseModelId, version}}}) => {
-
-       return {
-               onVersionControllerAction: (action, version, comment) =>
-                       LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action, version, comment}).then(updatedVersion => {
-                               ScreensHelper.loadScreen(dispatch, {screen, screenType: screenTypes.LICENSE_MODEL, props: {licenseModelId, version: updatedVersion}});
-                       }),
-
-               onOpenCommentCommitModal: ({onCommit, title}) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.COMMIT_COMMENT,
-                               modalComponentProps: {
-                                       onCommit,
-                                       type: CommitModalType.COMMIT
-                               },
-                               title
-                       }
-               }),
-
-               onVersionSwitching: version => {
-                       ScreensHelper.loadScreen(dispatch, {screen, screenType: screenTypes.LICENSE_MODEL, props: {licenseModelId, version}});
-               },
-
-               onManagePermissions() {
-                       PermissionsActionHelper.openPermissonsManager(dispatch, {itemId: licenseModelId, askForRights: false});
-               },
-
-               onMoreVersionsClick: ({itemName, users}) => {
-                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.VERSIONS_PAGE, screenType: screenTypes.LICENSE_MODEL,
-                               props: {licenseModelId, licenseModel: {name: itemName}, usersList: users}});
-               },
-
-               onOpenPermissions: ({users}) => {
-                       return PermissionsActionHelper.fetchItemUsers(dispatch, {itemId: licenseModelId, allUsers: users});
-               },
-
-               onOpenRevisionsModal: () => {
-                       return RevisionsActionHelper.openRevisionsView(dispatch, {itemId: licenseModelId, version: version, itemType: screenTypes.LICENSE_MODEL});
-               },
-
-               onNavigate: ({id}) => {
-                       ScreensHelper.loadScreen(dispatch, {screen: id, screenType: screenTypes.LICENSE_MODEL, props: {licenseModelId, version}});
-               }
-       };
+const mapActionsToProps = (
+    dispatch,
+    { currentScreen: { screen, props: { licenseModelId, version } } }
+) => {
+    return {
+        onVersionControllerAction: (action, version, comment) =>
+            LicenseModelActionHelper.performVCAction(dispatch, {
+                licenseModelId,
+                action,
+                version,
+                comment
+            }).then(updatedVersion => {
+                ScreensHelper.loadScreen(dispatch, {
+                    screen,
+                    screenType: screenTypes.LICENSE_MODEL,
+                    props: { licenseModelId, version: updatedVersion }
+                });
+            }),
+
+        onOpenCommentCommitModal: ({ onCommit, title }) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.COMMIT_COMMENT,
+                    modalComponentProps: {
+                        onCommit,
+                        type: CommitModalType.COMMIT
+                    },
+                    title
+                }
+            }),
+
+        onVersionSwitching: version => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen,
+                screenType: screenTypes.LICENSE_MODEL,
+                props: { licenseModelId, version }
+            });
+        },
+
+        onManagePermissions() {
+            PermissionsActionHelper.openPermissonsManager(dispatch, {
+                itemId: licenseModelId,
+                askForRights: false
+            });
+        },
+
+        onMoreVersionsClick: ({ itemName, users }) => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.VERSIONS_PAGE,
+                screenType: screenTypes.LICENSE_MODEL,
+                props: {
+                    licenseModelId,
+                    licenseModel: { name: itemName },
+                    usersList: users
+                }
+            });
+        },
+
+        onOpenPermissions: ({ users }) => {
+            return PermissionsActionHelper.fetchItemUsers(dispatch, {
+                itemId: licenseModelId,
+                allUsers: users
+            });
+        },
+
+        onOpenRevisionsModal: () => {
+            return RevisionsActionHelper.openRevisionsView(dispatch, {
+                itemId: licenseModelId,
+                version: version,
+                itemType: screenTypes.LICENSE_MODEL
+            });
+        },
+
+        onNavigate: ({ id }) => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: id,
+                screenType: screenTypes.LICENSE_MODEL,
+                props: { licenseModelId, version }
+            });
+        }
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(TabulatedEditor);
index d1d3a77..cfff9f1 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './LicenseModelConstants.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {actionsEnum as vcActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import { actionTypes } from './LicenseModelConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionsEnum as vcActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import LicenseAgreementActionHelper from './licenseAgreement/LicenseAgreementActionHelper.js';
 import FeatureGroupsActionHelper from './featureGroups/FeatureGroupsActionHelper.js';
 import EntitlementPoolsActionHelper from './entitlementPools/EntitlementPoolsActionHelper.js';
 import LicenseKeyGroupsActionHelper from './licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
-import {default as ItemsHelper} from 'sdc-app/common/helpers/ItemsHelper.js';
+import { default as ItemsHelper } from 'sdc-app/common/helpers/ItemsHelper.js';
 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import {itemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
-import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
-import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-license-models/`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-license-models/`;
 }
 
 function fetchLicenseModels() {
-       return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`
+    );
 }
 
 function fetchFinalizedLicenseModels() {
-       return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`
+    );
 }
 function fetchArchivedLicenseModels() {
-       return RestAPIUtil.fetch(`${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`
+    );
 }
 function fetchLicenseModelById(licenseModelId, version) {
-       const {id: versionId} = version;
-       return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}/versions/${versionId}`);
+    const { id: versionId } = version;
+    return RestAPIUtil.fetch(
+        `${baseUrl()}${licenseModelId}/versions/${versionId}`
+    );
 }
 
 function putLicenseModel(licenseModel) {
-       let {id, vendorName, description, iconRef, version: {id: versionId}} = licenseModel;
-       return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}`, {
-               vendorName,
-               description,
-               iconRef
-       });
+    let {
+        id,
+        vendorName,
+        description,
+        iconRef,
+        version: { id: versionId }
+    } = licenseModel;
+    return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}`, {
+        vendorName,
+        description,
+        iconRef
+    });
 }
 
-function putLicenseModelAction({itemId, action, version}) {
-       const {id: versionId} = version;
-       return RestAPIUtil.put(`${baseUrl()}${itemId}/versions/${versionId}/actions`, {action: action});
+function putLicenseModelAction({ itemId, action, version }) {
+    const { id: versionId } = version;
+    return RestAPIUtil.put(
+        `${baseUrl()}${itemId}/versions/${versionId}/actions`,
+        { action: action }
+    );
 }
 
 const LicenseModelActionHelper = {
+    fetchLicenseModels(dispatch) {
+        return fetchLicenseModels().then(response => {
+            dispatch({
+                type: actionTypes.LICENSE_MODELS_LIST_LOADED,
+                response
+            });
+        });
+    },
 
-       fetchLicenseModels(dispatch) {
-               return fetchLicenseModels().then(response => {
-                       dispatch({
-                               type: actionTypes.LICENSE_MODELS_LIST_LOADED,
-                               response
-                       });
-               });
-       },
+    fetchFinalizedLicenseModels(dispatch) {
+        return fetchFinalizedLicenseModels().then(response =>
+            dispatch({
+                type: actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED,
+                response
+            })
+        );
+    },
 
-       fetchFinalizedLicenseModels(dispatch) {
-               return fetchFinalizedLicenseModels().then(response => dispatch({
-                       type: actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED,
-                       response
-               }));
+    fetchArchivedLicenseModels(dispatch) {
+        return fetchArchivedLicenseModels().then(response =>
+            dispatch({
+                type: actionTypes.ARCHIVED_LICENSE_MODELS_LIST_LOADED,
+                response
+            })
+        );
+    },
 
-       },
+    fetchLicenseModelById(dispatch, { licenseModelId, version }) {
+        return fetchLicenseModelById(licenseModelId, version).then(response => {
+            dispatch({
+                type: actionTypes.LICENSE_MODEL_LOADED,
+                response: { ...response, version }
+            });
+        });
+    },
 
-       fetchArchivedLicenseModels(dispatch) {
-               return fetchArchivedLicenseModels().then(response => dispatch({
-                       type: actionTypes.ARCHIVED_LICENSE_MODELS_LIST_LOADED,
-                       response
-               }));
+    fetchLicenseModelItems(dispatch, { licenseModelId, version }) {
+        return Promise.all([
+            LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
+                licenseModelId,
+                version
+            }),
+            FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+                licenseModelId,
+                version
+            }),
+            EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {
+                licenseModelId,
+                version
+            }),
+            LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {
+                licenseModelId,
+                version
+            })
+        ]);
+    },
 
-       },
+    manageSubmitAction(dispatch, { licenseModelId, version, isDirty }) {
+        if (isDirty) {
+            const onCommit = comment => {
+                return this.performVCAction(dispatch, {
+                    licenseModelId,
+                    action: vcActionsEnum.COMMIT,
+                    version,
+                    comment
+                }).then(() => {
+                    return this.performSubmitAction(dispatch, {
+                        licenseModelId,
+                        version
+                    });
+                });
+            };
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.COMMIT_COMMENT,
+                    modalComponentProps: {
+                        onCommit,
+                        type: CommitModalType.COMMIT_SUBMIT
+                    },
+                    title: i18n('Commit & Submit')
+                }
+            });
+            return Promise.reject();
+        }
+        return this.performSubmitAction(dispatch, { licenseModelId, version });
+    },
 
-       fetchLicenseModelById(dispatch, {licenseModelId, version}) {
+    performSubmitAction(dispatch, { licenseModelId, version }) {
+        return putLicenseModelAction({
+            itemId: licenseModelId,
+            action: vcActionsEnum.SUBMIT,
+            version
+        }).then(() => {
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            }).then(updatedVersion => {
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
+                    data: {
+                        title: i18n('Submit Succeeded'),
+                        msg: i18n('This license model successfully submitted'),
+                        cancelButtonText: i18n('OK'),
+                        timeout: 2000
+                    }
+                });
+                versionPageActionHelper.fetchVersions(dispatch, {
+                    itemType: itemTypes.LICENSE_MODEL,
+                    itemId: licenseModelId
+                });
+                return Promise.resolve(updatedVersion);
+            });
+        });
+    },
 
-               return fetchLicenseModelById(licenseModelId, version).then(response => {
-                       dispatch({
-                               type: actionTypes.LICENSE_MODEL_LOADED,
-                               response: {...response, version}
-                       });
-               });
-       },
-
-       fetchLicenseModelItems(dispatch, {licenseModelId, version}) {
-               return Promise.all([
-                       LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version}),
-                       FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version}),
-                       EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}),
-                       LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version})
-               ]);
-       },
-
-       manageSubmitAction(dispatch, {licenseModelId, version, isDirty}) {
-               if(isDirty) {
-                       const onCommit = comment => {
-                               return this.performVCAction(dispatch, {licenseModelId, action: vcActionsEnum.COMMIT, version, comment}).then(() => {
-                                       return this.performSubmitAction(dispatch, {licenseModelId, version});
-                               });
-                       };
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                               data: {
-                                       modalComponentName: modalContentMapper.COMMIT_COMMENT,
-                                       modalComponentProps: {
-                                               onCommit,
-                                               type: CommitModalType.COMMIT_SUBMIT
-                                       },
-                                       title: i18n('Commit & Submit')
-                               }
-                       });
-                       return Promise.reject();
-               }
-               return this.performSubmitAction(dispatch, {licenseModelId, version});
-       },
-
-       performSubmitAction(dispatch, {licenseModelId, version}) {
-               return putLicenseModelAction({itemId: licenseModelId, action: vcActionsEnum.SUBMIT, version}).then(() => {
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id}).then(updatedVersion => {
-                               dispatch({
-                                       type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
-                                       data: {
-                                               title: i18n('Submit Succeeded'),
-                                               msg: i18n('This license model successfully submitted'),
-                                               cancelButtonText: i18n('OK'),
-                                               timeout: 2000
-                                       }
-                               });
-                               versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: licenseModelId});
-                               return Promise.resolve(updatedVersion);
-                       });
-               });
-       },
-
-       performVCAction(dispatch, {licenseModelId, action, version, comment}) {
-               return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: licenseModelId, version}).then(({inMerge, isDirty, updatedVersion}) => {
-                       if ( (updatedVersion.status === catalogItemStatuses.CERTIFIED || updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED) && 
-                               (action === VersionControllerActionsEnum.COMMIT || action === VersionControllerActionsEnum.SYNC)) {
-                               versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: licenseModelId});
-                               const msg = updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED ? i18n('Item was Archived') : i18n('Item version already Certified');
-                               dispatch({
-                                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                                       data: {
-                                               title: i18n('Commit error'),
-                                               msg,
-                                               cancelButtonText: i18n('Cancel')
-                                       }
-                               });
-                               return Promise.resolve(updatedVersion);
-                       }
-                       if (!inMerge) {
-                               if(action === vcActionsEnum.SUBMIT) {
-                                       return this.manageSubmitAction(dispatch, {licenseModelId, version, isDirty});
-                               }
-                               else {
-                                       return ItemsHelper.performVCAction({itemId: licenseModelId, action, version, comment}).then(() => {
-                                               versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: licenseModelId});
-                                               if (action === vcActionsEnum.SYNC) {
-                                                       return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: licenseModelId, version}).then(({updatedVersion}) => {
-                                                               return Promise.resolve(updatedVersion);
-                                                       });
-                                               } else {
-                                                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                                               }
-                                       });
-                               }
-                       }
-               });
-       },
-
-       saveLicenseModel(dispatch, {licenseModel}) {
-               return putLicenseModel(licenseModel).then(() => {
-                       dispatch({
-                               type: actionTypes.LICENSE_MODEL_LOADED,
-                               response: licenseModel
-                       });
-                       const {id, version: {id: versionId}} = licenseModel;
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: id, versionId}).then(updatedVersion => {
-                               if (updatedVersion.status !== licenseModel.version.status) {
-                                       versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: licenseModel.id});
-                               }
-                       });
-               });
-       }
+    performVCAction(dispatch, { licenseModelId, action, version, comment }) {
+        return MergeEditorActionHelper.analyzeSyncResult(dispatch, {
+            itemId: licenseModelId,
+            version
+        }).then(({ inMerge, isDirty, updatedVersion }) => {
+            if (
+                (updatedVersion.status === catalogItemStatuses.CERTIFIED ||
+                    updatedVersion.archivedStatus ===
+                        catalogItemStatuses.ARCHIVED) &&
+                (action === VersionControllerActionsEnum.COMMIT ||
+                    action === VersionControllerActionsEnum.SYNC)
+            ) {
+                versionPageActionHelper.fetchVersions(dispatch, {
+                    itemType: itemTypes.LICENSE_MODEL,
+                    itemId: licenseModelId
+                });
+                const msg =
+                    updatedVersion.archivedStatus ===
+                    catalogItemStatuses.ARCHIVED
+                        ? i18n('Item was Archived')
+                        : i18n('Item version already Certified');
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                    data: {
+                        title: i18n('Commit error'),
+                        msg,
+                        cancelButtonText: i18n('Cancel')
+                    }
+                });
+                return Promise.resolve(updatedVersion);
+            }
+            if (!inMerge) {
+                if (action === vcActionsEnum.SUBMIT) {
+                    return this.manageSubmitAction(dispatch, {
+                        licenseModelId,
+                        version,
+                        isDirty
+                    });
+                } else {
+                    return ItemsHelper.performVCAction({
+                        itemId: licenseModelId,
+                        action,
+                        version,
+                        comment
+                    }).then(() => {
+                        versionPageActionHelper.fetchVersions(dispatch, {
+                            itemType: itemTypes.LICENSE_MODEL,
+                            itemId: licenseModelId
+                        });
+                        if (action === vcActionsEnum.SYNC) {
+                            return MergeEditorActionHelper.analyzeSyncResult(
+                                dispatch,
+                                { itemId: licenseModelId, version }
+                            ).then(({ updatedVersion }) => {
+                                return Promise.resolve(updatedVersion);
+                            });
+                        } else {
+                            return ItemsHelper.checkItemStatus(dispatch, {
+                                itemId: licenseModelId,
+                                versionId: version.id
+                            });
+                        }
+                    });
+                }
+            }
+        });
+    },
 
+    saveLicenseModel(dispatch, { licenseModel }) {
+        return putLicenseModel(licenseModel).then(() => {
+            dispatch({
+                type: actionTypes.LICENSE_MODEL_LOADED,
+                response: licenseModel
+            });
+            const { id, version: { id: versionId } } = licenseModel;
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: id,
+                versionId
+            }).then(updatedVersion => {
+                if (updatedVersion.status !== licenseModel.version.status) {
+                    versionPageActionHelper.fetchVersions(dispatch, {
+                        itemType: itemTypes.LICENSE_MODEL,
+                        itemId: licenseModel.id
+                    });
+                }
+            });
+        });
+    }
 };
 
 export default LicenseModelActionHelper;
index 08009ee..d97f682 100644 (file)
@@ -17,23 +17,22 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 export const actionTypes = keyMirror({
-       LICENSE_MODEL_LOADED: null,
-       LICENSE_MODELS_LIST_LOADED: null,
-       FINALIZED_LICENSE_MODELS_LIST_LOADED: null,
-       ARCHIVED_LICENSE_MODELS_LIST_LOADED: null,
-       EDIT_LICENSE_MODEL: null
+    LICENSE_MODEL_LOADED: null,
+    LICENSE_MODELS_LIST_LOADED: null,
+    FINALIZED_LICENSE_MODELS_LIST_LOADED: null,
+    ARCHIVED_LICENSE_MODELS_LIST_LOADED: null,
+    EDIT_LICENSE_MODEL: null
 });
 
-
 export const thresholdUnitType = {
-       ABSOLUTE: 'Absolute',
-       PERCENTAGE: 'Percentage'
+    ABSOLUTE: 'Absolute',
+    PERCENTAGE: 'Percentage'
 };
 
 export const optionsInputValues = {
-       THRESHOLD_UNITS: [
-               {enum: '', title: i18n('please select…')},
-               {enum: thresholdUnitType.ABSOLUTE, title: 'Absolute'},
-               {enum: thresholdUnitType.PERCENTAGE, title: '%'}
-       ]
-};
\ No newline at end of file
+    THRESHOLD_UNITS: [
+        { enum: '', title: i18n('please select…') },
+        { enum: thresholdUnitType.ABSOLUTE, title: 'Absolute' },
+        { enum: thresholdUnitType.PERCENTAGE, title: '%' }
+    ]
+};
index add5ac6..2d27679 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './LicenseModelConstants.js';
+import { actionTypes } from './LicenseModelConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.LICENSE_MODEL_LOADED:                  
-                       return {
-                               ...state,
-                               data: action.response
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.LICENSE_MODEL_LOADED:
+            return {
+                ...state,
+                data: action.response
+            };
+        default:
+            return state;
+    }
 };
index 36a190a..00d669c 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './LicenseModelConstants.js';
+import { actionTypes } from './LicenseModelConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.LICENSE_MODELS_LIST_LOADED:
-                       return [...action.response.results];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.LICENSE_MODELS_LIST_LOADED:
+            return [...action.response.results];
+        default:
+            return state;
+    }
 };
index f635532..f102d28 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {combineReducers} from 'redux';
+import { combineReducers } from 'redux';
 
 import activityLogReducer from 'sdc-app/common/activity-log/ActivityLogReducer.js';
 
@@ -32,56 +32,75 @@ import entitlementPoolsEditorReducer from './entitlementPools/EntitlementPoolsEd
 import licenseKeyGroupsEditorReducer from './licenseKeyGroups/LicenseKeyGroupsEditorReducer.js';
 import licenseKeyGroupsListReducer from './licenseKeyGroups/LicenseKeyGroupsListReducer.js';
 
-import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
+import { createPlainDataReducer } from 'sdc-app/common/reducers/PlainDataReducer.js';
 
-import {actionTypes as licenseModelOverviewConstants, VLM_DESCRIPTION_FORM} from './overview/LicenseModelOverviewConstants.js';
-import limitEditorReducer from './limits/LimitEditorReducer.js'; 
+import {
+    actionTypes as licenseModelOverviewConstants,
+    VLM_DESCRIPTION_FORM
+} from './overview/LicenseModelOverviewConstants.js';
+import limitEditorReducer from './limits/LimitEditorReducer.js';
 
 export default combineReducers({
-       licenseModelCreation: createPlainDataReducer(licenseModelCreationReducer),
-       licenseModelEditor: licenseModelEditorReducer,
+    licenseModelCreation: createPlainDataReducer(licenseModelCreationReducer),
+    licenseModelEditor: licenseModelEditorReducer,
 
-       licenseAgreement: combineReducers({
-               licenseAgreementEditor: createPlainDataReducer(licenseAgreementEditorReducer),
-               licenseAgreementList: licenseAgreementListReducer
-       }),
-       featureGroup: combineReducers({
-               featureGroupEditor: createPlainDataReducer(featureGroupsEditorReducer),
-               featureGroupsList: featureGroupsListReducer
-       }),
-       entitlementPool: combineReducers({
-               entitlementPoolEditor: createPlainDataReducer(entitlementPoolsEditorReducer),
-               entitlementPoolsList: entitlementPoolsListReducer
-       }),
-       licenseKeyGroup: combineReducers({
-               licenseKeyGroupsEditor: createPlainDataReducer(licenseKeyGroupsEditorReducer),
-               licenseKeyGroupsList: licenseKeyGroupsListReducer
-       }),
-       licenseModelOverview: combineReducers({
-               selectedTab: (state = null, action) => action.type === licenseModelOverviewConstants.LICENSE_MODEL_OVERVIEW_TAB_SELECTED ? action.buttonTab : state,
-               descriptionEditor: createPlainDataReducer(function(state = false, action) {
-                       if (action.type === licenseModelOverviewConstants.LM_DATA_CHANGED) {
-                               return {
-                                       ...state,
-                                       data : {
-                                               description : action.description
-                                       },
-                                       formReady: null,
-                                       formName: VLM_DESCRIPTION_FORM,
-                                       genericFieldInfo: {
-                                               'description': {
-                                                       isValid: true,
-                                                       errorText: '',
-                                                       validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
-                                               }
-                                       }
-                               };
-                               //return action.description;
-                       } else {
-                               return state;
-                       }
-               }
-       )}),
-       limitEditor: createPlainDataReducer(limitEditorReducer),
-       activityLog: activityLogReducer
+    licenseAgreement: combineReducers({
+        licenseAgreementEditor: createPlainDataReducer(
+            licenseAgreementEditorReducer
+        ),
+        licenseAgreementList: licenseAgreementListReducer
+    }),
+    featureGroup: combineReducers({
+        featureGroupEditor: createPlainDataReducer(featureGroupsEditorReducer),
+        featureGroupsList: featureGroupsListReducer
+    }),
+    entitlementPool: combineReducers({
+        entitlementPoolEditor: createPlainDataReducer(
+            entitlementPoolsEditorReducer
+        ),
+        entitlementPoolsList: entitlementPoolsListReducer
+    }),
+    licenseKeyGroup: combineReducers({
+        licenseKeyGroupsEditor: createPlainDataReducer(
+            licenseKeyGroupsEditorReducer
+        ),
+        licenseKeyGroupsList: licenseKeyGroupsListReducer
+    }),
+    licenseModelOverview: combineReducers({
+        selectedTab: (state = null, action) =>
+            action.type ===
+            licenseModelOverviewConstants.LICENSE_MODEL_OVERVIEW_TAB_SELECTED
+                ? action.buttonTab
+                : state,
+        descriptionEditor: createPlainDataReducer(function(
+            state = false,
+            action
+        ) {
+            if (action.type === licenseModelOverviewConstants.LM_DATA_CHANGED) {
+                return {
+                    ...state,
+                    data: {
+                        description: action.description
+                    },
+                    formReady: null,
+                    formName: VLM_DESCRIPTION_FORM,
+                    genericFieldInfo: {
+                        description: {
+                            isValid: true,
+                            errorText: '',
+                            validations: [
+                                { type: 'required', data: true },
+                                { type: 'maxLength', data: 1000 }
+                            ]
+                        }
+                    }
+                };
+                //return action.description;
+            } else {
+                return state;
+            }
+        })
+    }),
+    limitEditor: createPlainDataReducer(limitEditorReducer),
+    activityLog: activityLogReducer
 });
index 64bae3b..340d345 100644 (file)
  * permissions and limitations under the License.
  */
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {thresholdUnitType} from './LicenseModelConstants.js';
+import { thresholdUnitType } from './LicenseModelConstants.js';
 import Validator from 'nfvo-utils/Validator.js';
 
 export function validateStartDate(value, state) {
-       if (state.data.expiryDate) {
-               if (!value) {
-                       return {isValid: false, errorText: i18n('Start date has to be specified if expiry date is specified')};
-               }
-       }
-       return {isValid: true, errorText: ''};
+    if (state.data.expiryDate) {
+        if (!value) {
+            return {
+                isValid: false,
+                errorText: i18n(
+                    'Start date has to be specified if expiry date is specified'
+                )
+            };
+        }
+    }
+    return { isValid: true, errorText: '' };
 }
 
 export function thresholdValueValidation(value, state) {
-       let  unit = state.data.thresholdUnits;
-       if (unit === thresholdUnitType.PERCENTAGE) {
-               return Validator.validate('thresholdValue', value, [
-                       {type: 'numeric', data: true},
-                       {type: 'maximum', data: 100},
-                       {type: 'minimum', data: 0}]);
-       } else {
-               return Validator.validate('thresholdValue', value, [
-                       {type: 'numeric', data: true},
-               ]);
-       }
+    let unit = state.data.thresholdUnits;
+    if (unit === thresholdUnitType.PERCENTAGE) {
+        return Validator.validate('thresholdValue', value, [
+            { type: 'numeric', data: true },
+            { type: 'maximum', data: 100 },
+            { type: 'minimum', data: 0 }
+        ]);
+    } else {
+        return Validator.validate('thresholdValue', value, [
+            { type: 'numeric', data: true }
+        ]);
+    }
 }
index bcd6e7f..4bbab86 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import LicenseModelCreationActionHelper from './LicenseModelCreationActionHelper.js';
 import LicenseModelCreationView from './LicenseModelCreationView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import {itemTypes as versionItemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
 
-export const mapStateToProps = ({users: {usersList}, licenseModelList, finalizedLicenseModelList, archivedLicenseModelList, licenseModel: {licenseModelCreation}}) => {
-       let {genericFieldInfo} = licenseModelCreation;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-       let VLMNames = {};
+export const mapStateToProps = ({
+    users: { usersList },
+    licenseModelList,
+    finalizedLicenseModelList,
+    archivedLicenseModelList,
+    licenseModel: { licenseModelCreation }
+}) => {
+    let { genericFieldInfo } = licenseModelCreation;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    let VLMNames = {};
 
-       const allVlmList = [...licenseModelList, ...finalizedLicenseModelList,...archivedLicenseModelList];
-       allVlmList.map((item) => {
-               VLMNames[item.name.toLowerCase()] = item.id;
-       });
+    const allVlmList = [
+        ...licenseModelList,
+        ...finalizedLicenseModelList,
+        ...archivedLicenseModelList
+    ];
+    allVlmList.map(item => {
+        VLMNames[item.name.toLowerCase()] = item.id;
+    });
 
-       return {...licenseModelCreation, isFormValid: isFormValid, VLMNames, usersList};
+    return {
+        ...licenseModelCreation,
+        isFormValid: isFormValid,
+        VLMNames,
+        usersList
+    };
 };
 
-export const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onCancel: () => LicenseModelCreationActionHelper.close(dispatch),
-               onSubmit: (licenseModel, usersList) => {
-                       LicenseModelCreationActionHelper.close(dispatch);
-                       LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(response => {
-                               let {itemId, version} = response;
-                               LicenseModelActionHelper.fetchLicenseModels(dispatch).then(() =>
-                                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers: usersList}).then(() =>
-                                               VersionsPageActionHelper.fetchVersions(dispatch, {itemType: versionItemTypes.LICENSE_MODEL, itemId}).then(() =>
-                                                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.LICENSE_MODEL_OVERVIEW, screenType: screenTypes.LICENSE_MODEL,
-                                                               props: {licenseModelId: itemId, version}})
-                               )));
-                       });
-               },
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
+export const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onCancel: () => LicenseModelCreationActionHelper.close(dispatch),
+        onSubmit: (licenseModel, usersList) => {
+            LicenseModelCreationActionHelper.close(dispatch);
+            LicenseModelCreationActionHelper.createLicenseModel(dispatch, {
+                licenseModel
+            }).then(response => {
+                let { itemId, version } = response;
+                LicenseModelActionHelper.fetchLicenseModels(dispatch).then(() =>
+                    PermissionsActionHelper.fetchItemUsers(dispatch, {
+                        itemId,
+                        allUsers: usersList
+                    }).then(() =>
+                        VersionsPageActionHelper.fetchVersions(dispatch, {
+                            itemType: versionItemTypes.LICENSE_MODEL,
+                            itemId
+                        }).then(() =>
+                            ScreensHelper.loadScreen(dispatch, {
+                                screen: enums.SCREEN.LICENSE_MODEL_OVERVIEW,
+                                screenType: screenTypes.LICENSE_MODEL,
+                                props: { licenseModelId: itemId, version }
+                            })
+                        )
+                    )
+                );
+            });
+        },
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseModelCreationView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseModelCreationView
+);
index 87df138..e2b8d55 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './LicenseModelCreationConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes } from './LicenseModelCreationConstants.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';
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-license-models/`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-license-models/`;
 }
 
 function createLicenseModel(licenseModel) {
-       return RestAPIUtil.post(baseUrl(), {
-               vendorName: licenseModel.vendorName,
-               description: licenseModel.description,
-               iconRef: 'icon'
-       });
+    return RestAPIUtil.post(baseUrl(), {
+        vendorName: licenseModel.vendorName,
+        description: licenseModel.description,
+        iconRef: 'icon'
+    });
 }
 
-
 export default {
+    open(dispatch) {
+        dispatch({
+            type: actionTypes.OPEN
+        });
 
-       open(dispatch) {
-               dispatch({
-                       type: actionTypes.OPEN
-               });
-
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.LICENSE_MODEL_CREATION,
-                               title: i18n('New License Model')
-                       }
-               });
-       },
-
-       close(dispatch){
-               dispatch({
-                       type: actionTypes.CLOSE
-               });
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName: modalContentMapper.LICENSE_MODEL_CREATION,
+                title: i18n('New License Model')
+            }
+        });
+    },
 
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-       },
+    close(dispatch) {
+        dispatch({
+            type: actionTypes.CLOSE
+        });
 
-       createLicenseModel(dispatch, {licenseModel}){
-               return createLicenseModel(licenseModel).then(result => {
-                       dispatch({
-                               type: actionTypes.LICENSE_MODEL_CREATED,
-                               result
-                       });
-                       return result;
-               });
-       }
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+    },
 
+    createLicenseModel(dispatch, { licenseModel }) {
+        return createLicenseModel(licenseModel).then(result => {
+            dispatch({
+                type: actionTypes.LICENSE_MODEL_CREATED,
+                result
+            });
+            return result;
+        });
+    }
 };
index e9b1c46..1cd61a9 100644 (file)
@@ -16,9 +16,9 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       OPEN: null,
-       CLOSE: null,
-       LICENSE_MODEL_CREATED: null
+    OPEN: null,
+    CLOSE: null,
+    LICENSE_MODEL_CREATED: null
 });
 
 export const LICENSE_MODEL_CREATION_FORM_NAME = 'LMCREATIONFORM';
index 879d356..7137230 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js';
+import {
+    actionTypes,
+    LICENSE_MODEL_CREATION_FORM_NAME
+} from './LicenseModelCreationConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.OPEN:
-                       return {
-                               ...state,
-                               formReady: null,
-                               formName: LICENSE_MODEL_CREATION_FORM_NAME,
-                               data: {},
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
-                                       },
-                                       'vendorName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}]
-                                       }
-                               }
-                       };
-               case actionTypes.CLOSE:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.OPEN:
+            return {
+                ...state,
+                formReady: null,
+                formName: LICENSE_MODEL_CREATION_FORM_NAME,
+                data: {},
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 1000 }
+                        ]
+                    },
+                    vendorName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 25 }
+                        ]
+                    }
+                }
+            };
+        case actionTypes.CLOSE:
+            return {};
+        default:
+            return state;
+    }
 };
index 948bdc1..59c4152 100644 (file)
@@ -19,84 +19,112 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import Validator from 'nfvo-utils/Validator.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import Form from 'nfvo-components/input/validation/Form.jsx';
-import {LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js';
+import { LICENSE_MODEL_CREATION_FORM_NAME } from './LicenseModelCreationConstants.js';
 
 const LicenseModelPropType = PropTypes.shape({
-       id: PropTypes.string,
-       vendorName: PropTypes.string,
-       description: PropTypes.string
+    id: PropTypes.string,
+    vendorName: PropTypes.string,
+    description: PropTypes.string
 });
 
 class LicenseModelCreationView extends React.Component {
+    static propTypes = {
+        data: LicenseModelPropType,
+        VLMNames: PropTypes.object,
+        usersList: PropTypes.array,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onValidateForm: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               data: LicenseModelPropType,
-               VLMNames: PropTypes.object,
-               usersList: PropTypes.array,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onValidateForm: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
+    render() {
+        let { data = {}, onDataChanged, genericFieldInfo } = this.props;
+        let { vendorName, description } = data;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        submitButtonText={i18n('Create')}
+                        onReset={() => this.props.onCancel()}
+                        labledButtons={true}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() => this.validate()}>
+                        <Input
+                            value={vendorName}
+                            label={i18n('Vendor Name')}
+                            data-test-id="vendor-name"
+                            onChange={vendorName =>
+                                onDataChanged(
+                                    { vendorName },
+                                    LICENSE_MODEL_CREATION_FORM_NAME,
+                                    {
+                                        vendorName: name =>
+                                            this.validateName(name)
+                                    }
+                                )
+                            }
+                            isValid={genericFieldInfo.vendorName.isValid}
+                            errorText={genericFieldInfo.vendorName.errorText}
+                            type="text"
+                            isRequired={true}
+                            className="field-section"
+                        />
+                        <Input
+                            isRequired={true}
+                            value={description}
+                            label={i18n('Description')}
+                            data-test-id="vendor-description"
+                            overlayPos="bottom"
+                            onChange={description =>
+                                onDataChanged(
+                                    { description },
+                                    LICENSE_MODEL_CREATION_FORM_NAME
+                                )
+                            }
+                            isValid={genericFieldInfo.description.isValid}
+                            errorText={genericFieldInfo.description.errorText}
+                            type="textarea"
+                            className="field-section"
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       render() {
-               let {data = {}, onDataChanged, genericFieldInfo} = this.props;
-               let {vendorName, description} = data;
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       ref='validationForm'
-                                       hasButtons={true}
-                                       onSubmit={ () => this.submit() }
-                                       submitButtonText={i18n('Create')}
-                                       onReset={ () => this.props.onCancel() }
-                                       labledButtons={true}
-                                       isValid={this.props.isFormValid}
-                                       formReady={this.props.formReady}
-                                       onValidateForm={() => this.validate() }>
-                                       <Input
-                                               value={vendorName}
-                                               label={i18n('Vendor Name')}
-                                               data-test-id='vendor-name'
-                                               onChange={vendorName => onDataChanged({vendorName}, LICENSE_MODEL_CREATION_FORM_NAME, {vendorName: name => this.validateName(name)})}
-                                               isValid={genericFieldInfo.vendorName.isValid}
-                                               errorText={genericFieldInfo.vendorName.errorText}
-                                               type='text'
-                                               isRequired={true}
-                                               className='field-section'/>
-                                       <Input
-                                               isRequired={true}
-                                               value={description}
-                                               label={i18n('Description')}
-                                               data-test-id='vendor-description'
-                                               overlayPos='bottom'
-                                               onChange={description => onDataChanged({description}, LICENSE_MODEL_CREATION_FORM_NAME)}
-                                               isValid={genericFieldInfo.description.isValid}
-                                               errorText={genericFieldInfo.description.errorText}
-                                               type='textarea'
-                                               className='field-section'/>
-                               </Form>}
-                       </div>
-               );
-       }
+    submit() {
+        const { data: licenseModel, usersList } = this.props;
+        this.props.onSubmit(licenseModel, usersList);
+    }
 
+    validateName(value) {
+        const { data: { id }, VLMNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: VLMNames
+        });
 
-       submit() {
-               const {data:licenseModel, usersList} = this.props;
-               this.props.onSubmit(licenseModel, usersList);
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "License model by the name '" +
+                          value +
+                          "' already exists. License model name must be unique"
+                  )
+              };
+    }
 
-       validateName(value) {
-               const {data: {id}, VLMNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: VLMNames});
-
-               return !isExists ?  {isValid: true, errorText: ''} :
-                       {isValid: false, errorText: i18n('License model by the name \'' + value + '\' already exists. License model name must be unique')};
-       }
-
-       validate() {
-               this.props.onValidateForm(LICENSE_MODEL_CREATION_FORM_NAME);
-       }
+    validate() {
+        this.props.onValidateForm(LICENSE_MODEL_CREATION_FORM_NAME);
+    }
 }
 
 export default LicenseModelCreationView;
index 84bdac8..181fc11 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes as entitlementPoolsActionTypes } from './EntitlementPoolsConstants.js';
-import {actionTypes as limitEditorActions} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
-import {default as getValue, getStrValue} from 'nfvo-utils/getValue.js';
+import { actionTypes as entitlementPoolsActionTypes } from './EntitlementPoolsConstants.js';
+import { actionTypes as limitEditorActions } from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import { default as getValue, getStrValue } from 'nfvo-utils/getValue.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 function baseUrl(licenseModelId, version) {
-       const restPrefix = Configuration.get('restPrefix');
-       const {id: versionId} = version;
-       return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/entitlement-pools`;
+    const restPrefix = Configuration.get('restPrefix');
+    const { id: versionId } = version;
+    return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/entitlement-pools`;
 }
 
 function fetchEntitlementPoolsList(licenseModelId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
 }
 
 function postEntitlementPool(licenseModelId, entitlementPool, version) {
-       return RestAPIUtil.post(baseUrl(licenseModelId, version), {
-               name: entitlementPool.name,
-               description: entitlementPool.description,
-               thresholdValue: entitlementPool.thresholdValue,
-               thresholdUnits: getValue(entitlementPool.thresholdUnits),
-               increments: entitlementPool.increments,
-               operationalScope: getValue(entitlementPool.operationalScope),
-               time: entitlementPool.time,
-               startDate: entitlementPool.startDate,
-               expiryDate: entitlementPool.expiryDate
-       });
+    return RestAPIUtil.post(baseUrl(licenseModelId, version), {
+        name: entitlementPool.name,
+        description: entitlementPool.description,
+        thresholdValue: entitlementPool.thresholdValue,
+        thresholdUnits: getValue(entitlementPool.thresholdUnits),
+        increments: entitlementPool.increments,
+        operationalScope: getValue(entitlementPool.operationalScope),
+        time: entitlementPool.time,
+        startDate: entitlementPool.startDate,
+        expiryDate: entitlementPool.expiryDate
+    });
 }
 
-
-function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version) {
-
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPool.id}`, {
-               name: entitlementPool.name,
-               description: entitlementPool.description,
-               thresholdValue: entitlementPool.thresholdValue,
-               thresholdUnits: getValue(entitlementPool.thresholdUnits),
-               increments: entitlementPool.increments,
-               operationalScope: getValue(entitlementPool.operationalScope),
-               time: entitlementPool.time,
-               startDate: entitlementPool.startDate,
-               expiryDate: entitlementPool.expiryDate
-       });
+function putEntitlementPool(
+    licenseModelId,
+    previousEntitlementPool,
+    entitlementPool,
+    version
+) {
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${entitlementPool.id}`,
+        {
+            name: entitlementPool.name,
+            description: entitlementPool.description,
+            thresholdValue: entitlementPool.thresholdValue,
+            thresholdUnits: getValue(entitlementPool.thresholdUnits),
+            increments: entitlementPool.increments,
+            operationalScope: getValue(entitlementPool.operationalScope),
+            time: entitlementPool.time,
+            startDate: entitlementPool.startDate,
+            expiryDate: entitlementPool.expiryDate
+        }
+    );
 }
 
 function deleteEntitlementPool(licenseModelId, entitlementPoolId, version) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(licenseModelId, version)}/${entitlementPoolId}`
+    );
 }
 
 function fetchLimitsList(licenseModelId, entitlementPoolId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`);
+    return RestAPIUtil.fetch(
+        `${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`
+    );
 }
 
 function deleteLimit(licenseModelId, entitlementPoolId, version, limitId) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits/${limitId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(
+            licenseModelId,
+            version
+        )}/${entitlementPoolId}/limits/${limitId}`
+    );
 }
 
 function postLimit(licenseModelId, entitlementPoolId, version, limit) {
-       return RestAPIUtil.post(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`, {
-               name: limit.name,
-               type: limit.type,
-               description: limit.description,
-               metric: getStrValue(limit.metric),
-               value: limit.value,
-               unit: getStrValue(limit.unit),
-               aggregationFunction: getValue(limit.aggregationFunction),
-               time: getValue(limit.time)
-       });
+    return RestAPIUtil.post(
+        `${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`,
+        {
+            name: limit.name,
+            type: limit.type,
+            description: limit.description,
+            metric: getStrValue(limit.metric),
+            value: limit.value,
+            unit: getStrValue(limit.unit),
+            aggregationFunction: getValue(limit.aggregationFunction),
+            time: getValue(limit.time)
+        }
+    );
 }
 
 function putLimit(licenseModelId, entitlementPoolId, version, limit) {
-
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits/${limit.id}`, {
-               name: limit.name,
-               type: limit.type,
-               description: limit.description,
-               metric: getStrValue(limit.metric),
-               value: limit.value,
-               unit: getStrValue(limit.unit),
-               aggregationFunction: getValue(limit.aggregationFunction),
-               time: getValue(limit.time)
-       });
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits/${
+            limit.id
+        }`,
+        {
+            name: limit.name,
+            type: limit.type,
+            description: limit.description,
+            metric: getStrValue(limit.metric),
+            value: limit.value,
+            unit: getStrValue(limit.unit),
+            aggregationFunction: getValue(limit.aggregationFunction),
+            time: getValue(limit.time)
+        }
+    );
 }
 
 export default {
+    fetchEntitlementPoolsList(dispatch, { licenseModelId, version }) {
+        return fetchEntitlementPoolsList(licenseModelId, version).then(
+            response =>
+                dispatch({
+                    type:
+                        entitlementPoolsActionTypes.ENTITLEMENT_POOLS_LIST_LOADED,
+                    response
+                })
+        );
+    },
+
+    openEntitlementPoolsEditor(
+        dispatch,
+        { entitlementPool, licenseModelId, version } = {}
+    ) {
+        if (licenseModelId && version) {
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                entitlementPool
+            });
+        }
+        dispatch({
+            type: entitlementPoolsActionTypes.entitlementPoolsEditor.OPEN,
+            entitlementPool
+        });
+    },
+
+    deleteEntitlementPool(
+        dispatch,
+        { licenseModelId, entitlementPoolId, version }
+    ) {
+        return deleteEntitlementPool(
+            licenseModelId,
+            entitlementPoolId,
+            version
+        ).then(() => {
+            dispatch({
+                type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL,
+                entitlementPoolId
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    },
+
+    entitlementPoolsEditorDataChanged(dispatch, { deltaData }) {
+        dispatch({
+            type:
+                entitlementPoolsActionTypes.entitlementPoolsEditor.DATA_CHANGED,
+            deltaData
+        });
+    },
+
+    closeEntitlementPoolsEditor(dispatch) {
+        dispatch({
+            type: entitlementPoolsActionTypes.entitlementPoolsEditor.CLOSE
+        });
+    },
+
+    saveEntitlementPool(
+        dispatch,
+        { licenseModelId, previousEntitlementPool, entitlementPool, version }
+    ) {
+        if (previousEntitlementPool) {
+            return putEntitlementPool(
+                licenseModelId,
+                previousEntitlementPool,
+                entitlementPool,
+                version
+            ).then(() => {
+                dispatch({
+                    type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL,
+                    entitlementPool
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        } else {
+            return postEntitlementPool(
+                licenseModelId,
+                entitlementPool,
+                version
+            ).then(response => {
+                dispatch({
+                    type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL,
+                    entitlementPool: {
+                        ...entitlementPool,
+                        referencingFeatureGroups: [],
+                        id: response.value
+                    }
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        }
+    },
+
+    hideDeleteConfirm(dispatch) {
+        dispatch({
+            type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
+            entitlementPoolToDelete: false
+        });
+    },
+    openDeleteEntitlementPoolConfirm(dispatch, { entitlementPool }) {
+        dispatch({
+            type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
+            entitlementPoolToDelete: entitlementPool
+        });
+    },
+
+    fetchLimits(dispatch, { licenseModelId, version, entitlementPool }) {
+        return fetchLimitsList(
+            licenseModelId,
+            entitlementPool.id,
+            version
+        ).then(response => {
+            dispatch({
+                type:
+                    entitlementPoolsActionTypes.entitlementPoolsEditor
+                        .LIMITS_LIST_LOADED,
+                response
+            });
+        });
+    },
+
+    submitLimit(dispatch, { licenseModelId, version, entitlementPool, limit }) {
+        const propmise = limit.id
+            ? putLimit(licenseModelId, entitlementPool.id, version, limit)
+            : postLimit(licenseModelId, entitlementPool.id, version, limit);
+        return propmise.then(() => {
+            dispatch({
+                type: limitEditorActions.CLOSE
+            });
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                entitlementPool
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    },
 
-       fetchEntitlementPoolsList(dispatch, {licenseModelId, version}) {
-               return fetchEntitlementPoolsList(licenseModelId, version).then(response => dispatch({
-                       type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_LIST_LOADED,
-                       response
-               }));
-       },
-
-       openEntitlementPoolsEditor(dispatch, {entitlementPool, licenseModelId, version} = {}) {
-               if (licenseModelId && version) {
-                       this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
-               }
-               dispatch({
-                       type: entitlementPoolsActionTypes.entitlementPoolsEditor.OPEN,
-                       entitlementPool
-               });
-       },
-
-       deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId, version}) {
-               return deleteEntitlementPool(licenseModelId, entitlementPoolId, version).then(() => {
-                       dispatch({
-                               type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL,
-                               entitlementPoolId
-                       });
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
-
-       entitlementPoolsEditorDataChanged(dispatch, {deltaData}) {
-               dispatch({
-                       type: entitlementPoolsActionTypes.entitlementPoolsEditor.DATA_CHANGED,
-                       deltaData
-               });
-       },
-
-       closeEntitlementPoolsEditor(dispatch) {
-               dispatch({
-                       type: entitlementPoolsActionTypes.entitlementPoolsEditor.CLOSE
-               });
-       },
-
-       saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version}) {
-               if (previousEntitlementPool) {
-                       return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version).then(() => {
-                               dispatch({
-                                       type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL,
-                                       entitlementPool
-                               });
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-               else {
-                       return postEntitlementPool(licenseModelId, entitlementPool, version).then(response => {
-                               dispatch({
-                                       type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL,
-                                       entitlementPool: {
-                                               ...entitlementPool,
-                                               referencingFeatureGroups: [],
-                                               id: response.value
-                                       }
-                               });
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-       },
-
-       hideDeleteConfirm(dispatch) {
-               dispatch({
-                       type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
-                       entitlementPoolToDelete: false
-               });
-       },
-       openDeleteEntitlementPoolConfirm(dispatch, {entitlementPool}) {
-               dispatch({
-                       type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
-                       entitlementPoolToDelete: entitlementPool
-               });
-       },
-
-
-
-       fetchLimits(dispatch, {licenseModelId, version, entitlementPool}) {
-               return fetchLimitsList(licenseModelId, entitlementPool.id, version). then (response => {
-                       dispatch({
-                               type: entitlementPoolsActionTypes.entitlementPoolsEditor.LIMITS_LIST_LOADED,
-                               response
-                       });
-               });
-       },
-
-       submitLimit(dispatch, {licenseModelId, version, entitlementPool, limit}) {
-               const propmise  =  limit.id ? putLimit(licenseModelId,entitlementPool.id, version, limit)
-                       : postLimit(licenseModelId,entitlementPool.id, version, limit);
-               return propmise.then(() => {
-                       dispatch({
-                               type: limitEditorActions.CLOSE
-                       });
-                       this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
-
-       deleteLimit(dispatch, {licenseModelId, version, entitlementPool, limit}) {
-               return  deleteLimit(licenseModelId,entitlementPool.id, version, limit.id).then(() => {
-                       this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       }
+    deleteLimit(dispatch, { licenseModelId, version, entitlementPool, limit }) {
+        return deleteLimit(
+            licenseModelId,
+            entitlementPool.id,
+            version,
+            limit.id
+        ).then(() => {
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                entitlementPool
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    }
 };
index de2a87c..e69ff68 100644 (file)
  */
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import InputOptions, {
+    other as optionInputOther
+} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export const actionTypes = keyMirror({
+    ENTITLEMENT_POOLS_LIST_LOADED: null,
+    ADD_ENTITLEMENT_POOL: null,
+    EDIT_ENTITLEMENT_POOL: null,
+    DELETE_ENTITLEMENT_POOL: null,
 
-       ENTITLEMENT_POOLS_LIST_LOADED: null,
-       ADD_ENTITLEMENT_POOL: null,
-       EDIT_ENTITLEMENT_POOL: null,
-       DELETE_ENTITLEMENT_POOL: null,
-
-       entitlementPoolsEditor: {
-               OPEN: null,
-               CLOSE: null,
-               DATA_CHANGED: null,
-               LIMITS_LIST_LOADED: null
-       }
-
+    entitlementPoolsEditor: {
+        OPEN: null,
+        CLOSE: null,
+        DATA_CHANGED: null,
+        LIMITS_LIST_LOADED: null
+    }
 });
 
 export const enums = keyMirror({
-       SELECTED_FEATURE_GROUP_TAB: {
-               GENERAL: 1,
-               ENTITLEMENT_POOLS: 2,
-               LICENCE_KEY_GROUPS: 3
-       },
-       SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: {
-               ASSOCIATED_ENTITLEMENT_POOLS: 1,
-               AVAILABLE_ENTITLEMENT_POOLS: 2
-       }
+    SELECTED_FEATURE_GROUP_TAB: {
+        GENERAL: 1,
+        ENTITLEMENT_POOLS: 2,
+        LICENCE_KEY_GROUPS: 3
+    },
+    SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: {
+        ASSOCIATED_ENTITLEMENT_POOLS: 1,
+        AVAILABLE_ENTITLEMENT_POOLS: 2
+    }
 });
 
 export const defaultState = {
-       ENTITLEMENT_POOLS_EDITOR_DATA: {
-               entitlementMetric: {choice: '', other: ''},
-               aggregationFunction: {choice: '', other: ''},
-               operationalScope: {choices: [], other: ''},
-               time: {choice: '', other: ''}
-       }
+    ENTITLEMENT_POOLS_EDITOR_DATA: {
+        entitlementMetric: { choice: '', other: '' },
+        aggregationFunction: { choice: '', other: '' },
+        operationalScope: { choices: [], other: '' },
+        time: { choice: '', other: '' }
+    }
 };
 
 export const thresholdUnitType = {
-       ABSOLUTE: 'Absolute',
-       PERCENTAGE: 'Percentage'
+    ABSOLUTE: 'Absolute',
+    PERCENTAGE: 'Percentage'
 };
 
 export const optionsInputValues = {
-       OPERATIONAL_SCOPE: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Network_Wide', title: 'Network Wide'},
-               {enum: 'Availability_Zone', title: 'Availability Zone'},
-               {enum: 'Data_Center', title: 'Data Center'},
-               {enum: 'Tenant', title: 'Tenant'},
-               {enum: 'VM', title: 'VM'},
-               {enum: 'CPU', title: 'CPU'},
-               {enum: 'Core', title: 'Core'}
-       ],
-       TIME: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Hour', title: 'Hour'},
-               {enum: 'Day', title: 'Day'},
-               {enum: 'Month', title: 'Month'}
-       ],
-       AGGREGATE_FUNCTION: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Peak', title: 'Peak'},
-               {enum: 'Average', title: 'Average'}
-       ],
-       ENTITLEMENT_METRIC: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Software_Instances_Count', title: 'Software Instances'},
-               {enum: 'Core', title: 'Core'},
-               {enum: 'CPU', title: 'CPU'},
-               {enum: 'Trunks', title: 'Trunks'},
-               {enum: 'User', title: 'User'},
-               {enum: 'Subscribers', title: 'Subscribers'},
-               {enum: 'Tenants', title: 'Tenants'},
-               {enum: 'Tokens', title: 'Tokens'},
-               {enum: 'Seats', title: 'Seats'},
-               {enum: 'Units_TB', title: 'Units-TB'},
-               {enum: 'Units_GB', title: 'Units-GB'},
-               {enum: 'Units_MB', title: 'Units-MB'}
-       ]
+    OPERATIONAL_SCOPE: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Network_Wide', title: 'Network Wide' },
+        { enum: 'Availability_Zone', title: 'Availability Zone' },
+        { enum: 'Data_Center', title: 'Data Center' },
+        { enum: 'Tenant', title: 'Tenant' },
+        { enum: 'VM', title: 'VM' },
+        { enum: 'CPU', title: 'CPU' },
+        { enum: 'Core', title: 'Core' }
+    ],
+    TIME: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Hour', title: 'Hour' },
+        { enum: 'Day', title: 'Day' },
+        { enum: 'Month', title: 'Month' }
+    ],
+    AGGREGATE_FUNCTION: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Peak', title: 'Peak' },
+        { enum: 'Average', title: 'Average' }
+    ],
+    ENTITLEMENT_METRIC: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Software_Instances_Count', title: 'Software Instances' },
+        { enum: 'Core', title: 'Core' },
+        { enum: 'CPU', title: 'CPU' },
+        { enum: 'Trunks', title: 'Trunks' },
+        { enum: 'User', title: 'User' },
+        { enum: 'Subscribers', title: 'Subscribers' },
+        { enum: 'Tenants', title: 'Tenants' },
+        { enum: 'Tokens', title: 'Tokens' },
+        { enum: 'Seats', title: 'Seats' },
+        { enum: 'Units_TB', title: 'Units-TB' },
+        { enum: 'Units_GB', title: 'Units-GB' },
+        { enum: 'Units_MB', title: 'Units-MB' }
+    ]
 };
 
-export const extractValue = (item) => {
-       if (item === undefined) {return '';} //TODO fix it later
-       return  item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+export const extractValue = item => {
+    if (item === undefined) {
+        return '';
+    } //TODO fix it later
+    return item
+        ? item.choice === optionInputOther.OTHER
+          ? item.other
+          : InputOptions.getTitleByName(optionsInputValues, item.choice)
+        : '';
 };
 
-export const extractUnits = (units) => {
-       if (units === undefined) {return '';} //TODO fix it later
-       return units === 'Absolute' ? '' : '%';
+export const extractUnits = units => {
+    if (units === undefined) {
+        return '';
+    } //TODO fix it later
+    return units === 'Absolute' ? '' : '%';
 };
 
 export const tabIds = {
-       GENERAL: 'GENERAL',
-       SP_LIMITS: 'SP_LIMITS',
-       VENDOR_LIMITS: 'VENDOR_LIMITS',
-       ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
+    GENERAL: 'GENERAL',
+    SP_LIMITS: 'SP_LIMITS',
+    VENDOR_LIMITS: 'VENDOR_LIMITS',
+    ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
 };
 
-export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL';
\ No newline at end of file
+export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL';
index 23c260f..5fcdad9 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
 import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
 import LimitEditorActionHelper from '../limits/LimitEditorActionHelper.js';
 
-const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
+const mapStateToProps = ({ licenseModel: { entitlementPool } }) => {
+    let {
+        data,
+        genericFieldInfo,
+        formReady,
+        limitsList
+    } = entitlementPool.entitlementPoolEditor;
 
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let {data, genericFieldInfo, formReady, limitsList} = entitlementPool.entitlementPoolEditor;
+    let previousData,
+        EPNames = {};
+    const entitlementPoolId = data ? data.id : null;
+    if (entitlementPoolId) {
+        previousData = entitlementPool.entitlementPoolsList.find(
+            entitlementPool => entitlementPool.id === entitlementPoolId
+        );
+    }
 
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    const list = entitlementPool.entitlementPoolsList;
+    for (let i = 0; i < list.length; i++) {
+        EPNames[list[i].name.toLowerCase()] = list[i].id;
+    }
 
-       let previousData, EPNames = {};
-       const entitlementPoolId = data ? data.id : null;
-       if(entitlementPoolId) {
-               previousData = entitlementPool.entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId);
-       }
-
-       const list = entitlementPool.entitlementPoolsList;
-       for (let i = 0; i < list.length; i++) {
-               EPNames[list[i].name.toLowerCase()] = list[i].id;
-       }
-
-       return {
-               data,
-               genericFieldInfo,
-               previousData,
-               isFormValid,
-               formReady,
-               EPNames,
-               limitsList
-       };
+    return {
+        data,
+        genericFieldInfo,
+        previousData,
+        isFormValid,
+        formReady,
+        EPNames,
+        limitsList
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch),
-               onSubmit: ({previousEntitlementPool, entitlementPool, keepOpen}) => {
-                       if (!keepOpen) {EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch);}
-                       EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version});
-               },
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName),
-               onCloseLimitEditor: () => LimitEditorActionHelper.closeLimitsEditor(dispatch),
-               onOpenLimitEditor: (limit) => LimitEditorActionHelper.openLimitsEditor(dispatch, {limit})
-       };
+const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onCancel: () =>
+            EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch),
+        onSubmit: ({ previousEntitlementPool, entitlementPool, keepOpen }) => {
+            if (!keepOpen) {
+                EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(
+                    dispatch
+                );
+            }
+            EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {
+                licenseModelId,
+                previousEntitlementPool,
+                entitlementPool,
+                version
+            });
+        },
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName),
+        onCloseLimitEditor: () =>
+            LimitEditorActionHelper.closeLimitsEditor(dispatch),
+        onOpenLimitEditor: limit =>
+            LimitEditorActionHelper.openLimitsEditor(dispatch, { limit })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    EntitlementPoolsEditorView
+);
index be100f6..4556b87 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, defaultState, SP_ENTITLEMENT_POOL_FORM} from './EntitlementPoolsConstants.js';
+import {
+    actionTypes,
+    defaultState,
+    SP_ENTITLEMENT_POOL_FORM
+} from './EntitlementPoolsConstants.js';
 import moment from 'moment';
-import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.entitlementPoolsEditor.OPEN:
-                       let entitlementPoolData = {...action.entitlementPool};
-                       let {startDate, expiryDate} = entitlementPoolData;
-                       if (startDate) {
-                               entitlementPoolData.startDate = moment(startDate, DATE_FORMAT).format(DATE_FORMAT);
-                       }
-                       if (expiryDate) {
-                               entitlementPoolData.expiryDate = moment(expiryDate, DATE_FORMAT).format(DATE_FORMAT);
-                       }
-                       return {
-                               ...state,
-                               formReady: null,
-                               formName: SP_ENTITLEMENT_POOL_FORM,
-                               genericFieldInfo: {
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'increments' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 120}]
-                                       },
-                                       'operationalScope' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'thresholdUnits' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'thresholdValue' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },                                      
-                                       'startDate': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'expiryDate': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               },
-                               data: action.entitlementPool ? entitlementPoolData : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA
-                       };
-               case actionTypes.entitlementPoolsEditor.DATA_CHANGED:
-                       return {
-                               ...state,
-                               data: {
-                                       ...state.data,
-                                       ...action.deltaData
-                               }
-                       };
-               case actionTypes.entitlementPoolsEditor.CLOSE:
-                       return {};
-
-               case actionTypes.entitlementPoolsEditor.LIMITS_LIST_LOADED:
-                       return {
-                               ...state,
-                               limitsList: action.response.results
-                       };      
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.entitlementPoolsEditor.OPEN:
+            let entitlementPoolData = { ...action.entitlementPool };
+            let { startDate, expiryDate } = entitlementPoolData;
+            if (startDate) {
+                entitlementPoolData.startDate = moment(
+                    startDate,
+                    DATE_FORMAT
+                ).format(DATE_FORMAT);
+            }
+            if (expiryDate) {
+                entitlementPoolData.expiryDate = moment(
+                    expiryDate,
+                    DATE_FORMAT
+                ).format(DATE_FORMAT);
+            }
+            return {
+                ...state,
+                formReady: null,
+                formName: SP_ENTITLEMENT_POOL_FORM,
+                genericFieldInfo: {
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    increments: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 120 }]
+                    },
+                    operationalScope: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    thresholdUnits: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    thresholdValue: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    startDate: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    expiryDate: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                },
+                data: action.entitlementPool
+                    ? entitlementPoolData
+                    : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA
+            };
+        case actionTypes.entitlementPoolsEditor.DATA_CHANGED:
+            return {
+                ...state,
+                data: {
+                    ...state.data,
+                    ...action.deltaData
+                }
+            };
+        case actionTypes.entitlementPoolsEditor.CLOSE:
+            return {};
 
+        case actionTypes.entitlementPoolsEditor.LIMITS_LIST_LOADED:
+            return {
+                ...state,
+                limitsList: action.response.results
+            };
+        default:
+            return state;
+    }
 };
index efae7f3..46eda62 100644 (file)
@@ -25,307 +25,479 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import Button from 'sdc-ui/lib/react/Button.js';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {optionsInputValues as  EntitlementPoolsOptionsInputValues, SP_ENTITLEMENT_POOL_FORM, tabIds}  from  './EntitlementPoolsConstants.js';
-import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
-import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.js';
-import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import {
+    optionsInputValues as EntitlementPoolsOptionsInputValues,
+    SP_ENTITLEMENT_POOL_FORM,
+    tabIds
+} from './EntitlementPoolsConstants.js';
+import { optionsInputValues as LicenseModelOptionsInputValues } from '../LicenseModelConstants.js';
+import {
+    validateStartDate,
+    thresholdValueValidation
+} from '../LicenseModelValidations.js';
+import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 import Tabs from 'sdc-ui/lib/react/Tabs.js';
 import Tab from 'sdc-ui/lib/react/Tab.js';
 import EntitlementPoolsLimits from './EntitlementPoolsLimits.js';
-import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
+import {
+    limitType,
+    NEW_LIMIT_TEMP_ID
+} from '../limits/LimitEditorConstants.js';
 
 const EntitlementPoolPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       operationalScope: PropTypes.shape({
-               choices: PropTypes.array,
-               other: PropTypes.string
-       }),
-       thresholdUnits: PropTypes.string,
-       thresholdValue: PropTypes.string,
-       increments: PropTypes.string,
-       startDate: PropTypes.string,
-       expiryDate: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    operationalScope: PropTypes.shape({
+        choices: PropTypes.array,
+        other: PropTypes.string
+    }),
+    thresholdUnits: PropTypes.string,
+    thresholdValue: PropTypes.string,
+    increments: PropTypes.string,
+    startDate: PropTypes.string,
+    expiryDate: PropTypes.string
 });
 
-const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName,
-        thresholdValueValidation, validateStartDate}) => {
+const EntitlementPoolsFormContent = ({
+    data,
+    genericFieldInfo,
+    onDataChanged,
+    validateName,
+    thresholdValueValidation,
+    validateStartDate
+}) => {
+    let {
+        name,
+        description,
+        operationalScope,
+        thresholdUnits,
+        thresholdValue,
+        increments,
+        startDate,
+        expiryDate
+    } = data;
+    return (
+        <GridSection hasLastColSet>
+            <GridItem colSpan={2}>
+                <Input
+                    onChange={name =>
+                        onDataChanged({ name }, SP_ENTITLEMENT_POOL_FORM, {
+                            name: validateName
+                        })
+                    }
+                    isValid={genericFieldInfo.name.isValid}
+                    isRequired={true}
+                    errorText={genericFieldInfo.name.errorText}
+                    label={i18n('Name')}
+                    value={name}
+                    data-test-id="create-ep-name"
+                    type="text"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <InputOptions
+                    onInputChange={() => {}}
+                    isMultiSelect={true}
+                    onEnumChange={operationalScope =>
+                        onDataChanged(
+                            {
+                                operationalScope: {
+                                    choices: operationalScope,
+                                    other: ''
+                                }
+                            },
+                            SP_ENTITLEMENT_POOL_FORM
+                        )
+                    }
+                    onOtherChange={operationalScope =>
+                        onDataChanged(
+                            {
+                                operationalScope: {
+                                    choices: [optionInputOther.OTHER],
+                                    other: operationalScope
+                                }
+                            },
+                            SP_ENTITLEMENT_POOL_FORM
+                        )
+                    }
+                    label={i18n('Operational Scope')}
+                    data-test-id="create-ep-operational-scope"
+                    type="select"
+                    multiSelectedEnum={
+                        operationalScope && operationalScope.choices
+                    }
+                    otherValue={operationalScope && operationalScope.other}
+                    values={
+                        EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE
+                    }
+                    isValid={genericFieldInfo.operationalScope.isValid}
+                    errorText={genericFieldInfo.operationalScope.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2} stretch>
+                <Input
+                    onChange={description =>
+                        onDataChanged({ description }, SP_ENTITLEMENT_POOL_FORM)
+                    }
+                    isValid={genericFieldInfo.description.isValid}
+                    errorText={genericFieldInfo.description.errorText}
+                    label={i18n('Description')}
+                    value={description}
+                    data-test-id="create-ep-description"
+                    type="textarea"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <div className="threshold-section">
+                    <Input
+                        onChange={e => {
+                            // setting the unit to the correct value
+                            const selectedIndex = e.target.selectedIndex;
+                            const val = e.target.options[selectedIndex].value;
+                            onDataChanged(
+                                { thresholdUnits: val },
+                                SP_ENTITLEMENT_POOL_FORM
+                            );
+                            // TODO make sure that the value is valid too
+                            if (thresholdValue && thresholdValue !== '') {
+                                onDataChanged(
+                                    { thresholdValue: thresholdValue },
+                                    SP_ENTITLEMENT_POOL_FORM,
+                                    { thresholdValue: thresholdValueValidation }
+                                );
+                            }
+                        }}
+                        value={thresholdUnits}
+                        label={i18n('Threshold Units')}
+                        data-test-id="create-ep-threshold-units"
+                        isValid={genericFieldInfo.thresholdUnits.isValid}
+                        errorText={genericFieldInfo.thresholdUnits.errorText}
+                        groupClassName="bootstrap-input-options"
+                        className="input-options-select"
+                        type="select">
+                        {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(
+                            mtype => (
+                                <option key={mtype.enum} value={mtype.enum}>{`${
+                                    mtype.title
+                                }`}</option>
+                            )
+                        )}
+                    </Input>
 
-       let {name, description, operationalScope, thresholdUnits, thresholdValue,
-               increments, startDate, expiryDate} = data;
-       return (
-               <GridSection hasLastColSet>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       onChange={name => onDataChanged({name}, SP_ENTITLEMENT_POOL_FORM, {name: validateName})}
-                                       isValid={genericFieldInfo.name.isValid}
-                                       isRequired={true}
-                                       errorText={genericFieldInfo.name.errorText}
-                                       label={i18n('Name')}
-                                       value={name}
-                                       data-test-id='create-ep-name'
-                                       type='text'/>
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                               <InputOptions
-                                       onInputChange={()=>{}}
-                                       isMultiSelect={true}
-                                       onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
-                                               SP_ENTITLEMENT_POOL_FORM)}
-                                       onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
-                                               other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM)}
-                                       label={i18n('Operational Scope')}
-                                       data-test-id='create-ep-operational-scope'
-                                       type='select'
-                                       multiSelectedEnum={operationalScope && operationalScope.choices}
-                                       otherValue={operationalScope && operationalScope.other}
-                                       values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}
-                                       isValid={genericFieldInfo.operationalScope.isValid}
-                                       errorText={genericFieldInfo.operationalScope.errorText} />
-                       </GridItem>
-                       <GridItem colSpan={2} stretch>
-                               <Input
-                                       onChange={description => onDataChanged({description}, SP_ENTITLEMENT_POOL_FORM)}
-                                       isValid={genericFieldInfo.description.isValid}
-                                       errorText={genericFieldInfo.description.errorText}
-                                       label={i18n('Description')}
-                                       value={description}
-                                       data-test-id='create-ep-description'
-                                       type='textarea'/>
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                               <div className='threshold-section'>
-                                       <Input
-                                               onChange={e => {
-                                                       // setting the unit to the correct value
-                                                       const selectedIndex = e.target.selectedIndex;
-                                                       const val = e.target.options[selectedIndex].value;
-                                                       onDataChanged({thresholdUnits: val}, SP_ENTITLEMENT_POOL_FORM);
-                                                       // TODO make sure that the value is valid too
-                                                       if(thresholdValue && thresholdValue !== '') {
-                                                               onDataChanged({thresholdValue: thresholdValue}, SP_ENTITLEMENT_POOL_FORM,{thresholdValue : thresholdValueValidation});
-                                                       }}
-
-                                               }
-                                               value={thresholdUnits}
-                                               label={i18n('Threshold Units')}
-                                               data-test-id='create-ep-threshold-units'
-                                               isValid={genericFieldInfo.thresholdUnits.isValid}
-                                               errorText={genericFieldInfo.thresholdUnits.errorText}
-                                               groupClassName='bootstrap-input-options'
-                                               className='input-options-select'
-                                               type='select' >
-                                               {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
-                                                       <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                                       </Input>
-
-                                       <Input
-                                               className='entitlement-pools-form-row-threshold-value'
-                                               onChange={thresholdValue => onDataChanged({thresholdValue}, SP_ENTITLEMENT_POOL_FORM,
-                                                       {thresholdValue : thresholdValueValidation})}
-                                               label={i18n('Threshold Value')}
-                                               isValid={genericFieldInfo.thresholdValue.isValid}
-                                               errorText={genericFieldInfo.thresholdValue.errorText}
-                                               data-test-id='create-ep-threshold-value'
-                                               value={thresholdValue}
-                                               type='text'/>
-                               </div>
-                               <Input
-                                       onChange={increments => onDataChanged({increments}, SP_ENTITLEMENT_POOL_FORM)}
-                                       label={i18n('Increments')}
-                                       value={increments}
-                                       data-test-id='create-ep-increments'
-                                       type='text'/>
-                               <div className='date-section'>
-                                       <Input
-                                               type='date'
-                                               label={i18n('Start Date')}
-                                               value={startDate}
-                                               dateFormat={DATE_FORMAT}
-                                               startDate={startDate}
-                                               endDate={expiryDate}
-                                               onChange={startDate => onDataChanged(
-                                                       {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
-                                                       SP_ENTITLEMENT_POOL_FORM,
-                                                       {startDate: validateStartDate}
-                                               )}
-                                               isValid={genericFieldInfo.startDate.isValid}
-                                               errorText={genericFieldInfo.startDate.errorText}
-                                               selectsStart/>
-                                       <Input
-                                               type='date'
-                                               label={i18n('Expiry Date')}
-                                               value={expiryDate}
-                                               dateFormat={DATE_FORMAT}
-                                               startDate={startDate}
-                                               endDate={expiryDate}
-                                               onChange={expiryDate => {
-                                                       onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, SP_ENTITLEMENT_POOL_FORM);
-                                                       onDataChanged({startDate}, SP_ENTITLEMENT_POOL_FORM, {startDate: validateStartDate});
-                                               }}
-                                               isValid={genericFieldInfo.expiryDate.isValid}
-                                               errorText={genericFieldInfo.expiryDate.errorText}
-                                               selectsEnd/>
-                               </div>
-                       </GridItem>
-               </GridSection>
-       );
+                    <Input
+                        className="entitlement-pools-form-row-threshold-value"
+                        onChange={thresholdValue =>
+                            onDataChanged(
+                                { thresholdValue },
+                                SP_ENTITLEMENT_POOL_FORM,
+                                {
+                                    thresholdValue: thresholdValueValidation
+                                }
+                            )
+                        }
+                        label={i18n('Threshold Value')}
+                        isValid={genericFieldInfo.thresholdValue.isValid}
+                        errorText={genericFieldInfo.thresholdValue.errorText}
+                        data-test-id="create-ep-threshold-value"
+                        value={thresholdValue}
+                        type="text"
+                    />
+                </div>
+                <Input
+                    onChange={increments =>
+                        onDataChanged({ increments }, SP_ENTITLEMENT_POOL_FORM)
+                    }
+                    label={i18n('Increments')}
+                    value={increments}
+                    data-test-id="create-ep-increments"
+                    type="text"
+                />
+                <div className="date-section">
+                    <Input
+                        type="date"
+                        label={i18n('Start Date')}
+                        value={startDate}
+                        dateFormat={DATE_FORMAT}
+                        startDate={startDate}
+                        endDate={expiryDate}
+                        onChange={startDate =>
+                            onDataChanged(
+                                {
+                                    startDate: startDate
+                                        ? startDate.format(DATE_FORMAT)
+                                        : ''
+                                },
+                                SP_ENTITLEMENT_POOL_FORM,
+                                { startDate: validateStartDate }
+                            )
+                        }
+                        isValid={genericFieldInfo.startDate.isValid}
+                        errorText={genericFieldInfo.startDate.errorText}
+                        selectsStart
+                    />
+                    <Input
+                        type="date"
+                        label={i18n('Expiry Date')}
+                        value={expiryDate}
+                        dateFormat={DATE_FORMAT}
+                        startDate={startDate}
+                        endDate={expiryDate}
+                        onChange={expiryDate => {
+                            onDataChanged(
+                                {
+                                    expiryDate: expiryDate
+                                        ? expiryDate.format(DATE_FORMAT)
+                                        : ''
+                                },
+                                SP_ENTITLEMENT_POOL_FORM
+                            );
+                            onDataChanged(
+                                { startDate },
+                                SP_ENTITLEMENT_POOL_FORM,
+                                {
+                                    startDate: validateStartDate
+                                }
+                            );
+                        }}
+                        isValid={genericFieldInfo.expiryDate.isValid}
+                        errorText={genericFieldInfo.expiryDate.errorText}
+                        selectsEnd
+                    />
+                </div>
+            </GridItem>
+        </GridSection>
+    );
 };
 
 class EntitlementPoolsEditorView extends React.Component {
+    static propTypes = {
+        data: EntitlementPoolPropType,
+        previousData: EntitlementPoolPropType,
+        EPNames: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               data: EntitlementPoolPropType,
-               previousData: EntitlementPoolPropType,
-               EPNames: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
-
-       static defaultProps = {
-               data: {}
-       };
-
-       componentDidUpdate(prevProps) {
-               if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
-                       this.submit();
-               }
-       }
+    static defaultProps = {
+        data: {}
+    };
 
-       state = {
-               selectedTab: tabIds.GENERAL,
-               selectedLimit: ''
-       };
+    componentDidUpdate(prevProps) {
+        if (
+            this.props.formReady &&
+            this.props.formReady !== prevProps.formReady
+        ) {
+            // if form validation succeeded -> continue with submit
+            this.submit();
+        }
+    }
 
-       render() {
-               let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo, onCloseLimitEditor, limitsList = []} = this.props;
-               const {selectedTab} = this.state;
-               const isTabsDisabled = !data.id || !this.props.isFormValid;
+    state = {
+        selectedTab: tabIds.GENERAL,
+        selectedLimit: ''
+    };
 
-               return (
-                       <div>
-                       <Tabs
-                               type='menu'
-                               activeTab={selectedTab}
-                               onTabClick={(tabIndex)=>{
-                                       if (tabIndex === tabIds.ADD_LIMIT_BUTTON)  {
-                                               this.onAddLimit();
-                                       } else {
-                                               this.setState({selectedTab: tabIndex});
-                                               this.setState({selectedLimit: ''});
-                                               onCloseLimitEditor();
-                                       }
-                               }}
-                               invalidTabs={[]}>
-                               <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
-                                       {
-                                               genericFieldInfo && <Form
-                                                       ref='validationForm'
-                                                       hasButtons={false}
-                                                       labledButtons={false}
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       isValid={this.props.isFormValid}
-                                                       formReady={this.props.formReady}
-                                                       onValidateForm={() => this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM) }
-                                                       className='license-model-form entitlement-pools-form'>
-                                                       <EntitlementPoolsFormContent
-                                                               data={data}
-                                                               genericFieldInfo={genericFieldInfo}
-                                                               onDataChanged={onDataChanged}
-                                                               validateName={(value) => this.validateName(value)}
-                                                               validateStartDate={(value, state) => validateStartDate(value, state)}
-                                                               thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
-                                               </Form>
-                                       }
-                               </Tab>
-                               <Tab disabled={isTabsDisabled} tabId={tabIds.SP_LIMITS} data-test-id='sp-limits-tab' title={i18n('SP Limits')}>
-                                       {selectedTab === tabIds.SP_LIMITS &&
-                                               <EntitlementPoolsLimits
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       limitType={limitType.SERVICE_PROVIDER}
-                                                       limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
-                                                       selectedLimit={this.state.selectedLimit}
-                                                       onCloseLimitEditor={() => this.onCloseLimitEditor()}
-                                                       onSelectLimit={limit => this.onSelectLimit(limit)}/>}
-                               </Tab>
-                               <Tab disabled={isTabsDisabled} tabId={tabIds.VENDOR_LIMITS} data-test-id='vendor-limits-tab' title={i18n('Vendor Limits')}>
-                                       {selectedTab === tabIds.VENDOR_LIMITS &&
-                                               <EntitlementPoolsLimits
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       limitType={limitType.VENDOR}
-                                                       limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
-                                                       selectedLimit={this.state.selectedLimit}
-                                                       onCloseLimitEditor={() => this.onCloseLimitEditor()}
-                                                       onSelectLimit={limit => this.onSelectLimit(limit)}/>}
-                               </Tab>
-                               {
-                                       selectedTab !== tabIds.GENERAL ?
-                                               <Button
-                                                       disabled={this.state.selectedLimit || isReadOnlyMode}
-                                                       className='add-limit-button'
-                                                       tabId={tabIds.ADD_LIMIT_BUTTON}
-                                                       btnType='link'
-                                                       iconName='plus'>
-                                                       {i18n('Add Limit')}
-                                               </Button>
-                                       :
-                                               <div key='empty_ep_tab_key'></div> // Render empty div to not break tabs
-                               }
-                       </Tabs>
-                       <GridSection className='license-model-modal-buttons entitlement-pools-editor-buttons'>
-                               {!this.state.selectedLimit &&
-                                       <Button btnType='default' disabled={!this.props.isFormValid || isReadOnlyMode} onClick={() => this.submit()} type='reset'>
-                                               {i18n('Save')}
-                                       </Button>
-                               }
-                       <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
-                               {i18n('Cancel')}
-                       </Button>
-                       </GridSection>
-                       </div>
-               );
-       }
+    render() {
+        let {
+            data = {},
+            onDataChanged,
+            isReadOnlyMode,
+            genericFieldInfo,
+            onCloseLimitEditor,
+            limitsList = []
+        } = this.props;
+        const { selectedTab } = this.state;
+        const isTabsDisabled = !data.id || !this.props.isFormValid;
 
-       submit() {
-               const {data: entitlementPool, previousData: previousEntitlementPool, formReady} = this.props;
-               if (!formReady) {
-                       this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM);
-               } else {
-                       this.props.onSubmit({entitlementPool, previousEntitlementPool});
-               }
-       }
+        return (
+            <div>
+                <Tabs
+                    type="menu"
+                    activeTab={selectedTab}
+                    onTabClick={tabIndex => {
+                        if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
+                            this.onAddLimit();
+                        } else {
+                            this.setState({ selectedTab: tabIndex });
+                            this.setState({ selectedLimit: '' });
+                            onCloseLimitEditor();
+                        }
+                    }}
+                    invalidTabs={[]}>
+                    <Tab
+                        tabId={tabIds.GENERAL}
+                        data-test-id="general-tab"
+                        title={i18n('General')}>
+                        {genericFieldInfo && (
+                            <Form
+                                ref="validationForm"
+                                hasButtons={false}
+                                labledButtons={false}
+                                isReadOnlyMode={isReadOnlyMode}
+                                isValid={this.props.isFormValid}
+                                formReady={this.props.formReady}
+                                onValidateForm={() =>
+                                    this.props.onValidateForm(
+                                        SP_ENTITLEMENT_POOL_FORM
+                                    )
+                                }
+                                className="license-model-form entitlement-pools-form">
+                                <EntitlementPoolsFormContent
+                                    data={data}
+                                    genericFieldInfo={genericFieldInfo}
+                                    onDataChanged={onDataChanged}
+                                    validateName={value =>
+                                        this.validateName(value)
+                                    }
+                                    validateStartDate={(value, state) =>
+                                        validateStartDate(value, state)
+                                    }
+                                    thresholdValueValidation={(value, state) =>
+                                        thresholdValueValidation(value, state)
+                                    }
+                                />
+                            </Form>
+                        )}
+                    </Tab>
+                    <Tab
+                        disabled={isTabsDisabled}
+                        tabId={tabIds.SP_LIMITS}
+                        data-test-id="sp-limits-tab"
+                        title={i18n('SP Limits')}>
+                        {selectedTab === tabIds.SP_LIMITS && (
+                            <EntitlementPoolsLimits
+                                isReadOnlyMode={isReadOnlyMode}
+                                limitType={limitType.SERVICE_PROVIDER}
+                                limitsList={limitsList.filter(
+                                    item =>
+                                        item.type === limitType.SERVICE_PROVIDER
+                                )}
+                                selectedLimit={this.state.selectedLimit}
+                                onCloseLimitEditor={() =>
+                                    this.onCloseLimitEditor()
+                                }
+                                onSelectLimit={limit =>
+                                    this.onSelectLimit(limit)
+                                }
+                            />
+                        )}
+                    </Tab>
+                    <Tab
+                        disabled={isTabsDisabled}
+                        tabId={tabIds.VENDOR_LIMITS}
+                        data-test-id="vendor-limits-tab"
+                        title={i18n('Vendor Limits')}>
+                        {selectedTab === tabIds.VENDOR_LIMITS && (
+                            <EntitlementPoolsLimits
+                                isReadOnlyMode={isReadOnlyMode}
+                                limitType={limitType.VENDOR}
+                                limitsList={limitsList.filter(
+                                    item => item.type === limitType.VENDOR
+                                )}
+                                selectedLimit={this.state.selectedLimit}
+                                onCloseLimitEditor={() =>
+                                    this.onCloseLimitEditor()
+                                }
+                                onSelectLimit={limit =>
+                                    this.onSelectLimit(limit)
+                                }
+                            />
+                        )}
+                    </Tab>
+                    {selectedTab !== tabIds.GENERAL ? (
+                        <Button
+                            disabled={
+                                this.state.selectedLimit || isReadOnlyMode
+                            }
+                            className="add-limit-button"
+                            tabId={tabIds.ADD_LIMIT_BUTTON}
+                            btnType="link"
+                            iconName="plus">
+                            {i18n('Add Limit')}
+                        </Button>
+                    ) : (
+                        <div key="empty_ep_tab_key" />
+                    ) // Render empty div to not break tabs
+                    }
+                </Tabs>
+                <GridSection className="license-model-modal-buttons entitlement-pools-editor-buttons">
+                    {!this.state.selectedLimit && (
+                        <Button
+                            btnType="default"
+                            disabled={!this.props.isFormValid || isReadOnlyMode}
+                            onClick={() => this.submit()}
+                            type="reset">
+                            {i18n('Save')}
+                        </Button>
+                    )}
+                    <Button
+                        btnType={
+                            this.state.selectedLimit ? 'default' : 'outline'
+                        }
+                        onClick={() => this.props.onCancel()}
+                        type="reset">
+                        {i18n('Cancel')}
+                    </Button>
+                </GridSection>
+            </div>
+        );
+    }
 
-       validateName(value) {
-               const {data: {id}, EPNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: EPNames});
+    submit() {
+        const {
+            data: entitlementPool,
+            previousData: previousEntitlementPool,
+            formReady
+        } = this.props;
+        if (!formReady) {
+            this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM);
+        } else {
+            this.props.onSubmit({ entitlementPool, previousEntitlementPool });
+        }
+    }
 
-               return !isExists ?  {isValid: true, errorText: ''} :
-               {isValid: false, errorText: i18n('Entitlement pool by the name \'' + value + '\' already exists. Entitlement pool name must be unique')};
-       }
+    validateName(value) {
+        const { data: { id }, EPNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: EPNames
+        });
 
-       onSelectLimit(limit) {
-               if (limit.id === this.state.selectedLimit) {
-                       this.setState({selectedLimit: ''});
-                       return;
-               }
-               this.setState({selectedLimit: limit.id});
-               this.props.onOpenLimitEditor(limit);
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "Entitlement pool by the name '" +
+                          value +
+                          "' already exists. Entitlement pool name must be unique"
+                  )
+              };
+    }
 
-       onCloseLimitEditor() {
-               this.setState({selectedLimit: ''});
-               this.props.onCloseLimitEditor();
-       }
+    onSelectLimit(limit) {
+        if (limit.id === this.state.selectedLimit) {
+            this.setState({ selectedLimit: '' });
+            return;
+        }
+        this.setState({ selectedLimit: limit.id });
+        this.props.onOpenLimitEditor(limit);
+    }
 
-       onAddLimit() {
-               this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
-               this.props.onOpenLimitEditor();
-       }
+    onCloseLimitEditor() {
+        this.setState({ selectedLimit: '' });
+        this.props.onCloseLimitEditor();
+    }
 
+    onAddLimit() {
+        this.setState({ selectedLimit: NEW_LIMIT_TEMP_ID });
+        this.props.onOpenLimitEditor();
+    }
 }
 
 export default EntitlementPoolsEditorView;
index 8300594..fd5fe6d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import Limits from 'sdc-app/onboarding/licenseModel/limits/Limits.jsx';
-import {actionTypes as globalModalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as globalModalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
 
-const mapStateToProps = ({licenseModel: {entitlementPool: {entitlementPoolEditor: {data}}, limitEditor}, currentScreen}) => {
-       let  {props: {licenseModelId, version}} = currentScreen;
-       return {
-               parent: data,
-               limitEditor,
-               licenseModelId,
-               version
-       };
+const mapStateToProps = ({
+    licenseModel: {
+        entitlementPool: { entitlementPoolEditor: { data } },
+        limitEditor
+    },
+    currentScreen
+}) => {
+    let { props: { licenseModelId, version } } = currentScreen;
+    return {
+        parent: data,
+        limitEditor,
+        licenseModelId,
+        version
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onSubmit: (limit, entitlementPool, licenseModelId, version) => EntitlementPoolsActionHelper.submitLimit(dispatch,
-                       {
-                               limit,
-                               entitlementPool,
-                               licenseModelId,
-                               version}),
-               onDelete: ({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit}) => dispatch({
-                       type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete {name}?', {name: limit.name}),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=> EntitlementPoolsActionHelper.deleteLimit(dispatch, {limit, entitlementPool: parent, licenseModelId, version}).then(() =>
-                                       selectedLimit === limit.id && onCloseLimitEditor()
-                               )
-                       }
-               })
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onSubmit: (limit, entitlementPool, licenseModelId, version) =>
+            EntitlementPoolsActionHelper.submitLimit(dispatch, {
+                limit,
+                entitlementPool,
+                licenseModelId,
+                version
+            }),
+        onDelete: ({
+            limit,
+            parent,
+            licenseModelId,
+            version,
+            onCloseLimitEditor,
+            selectedLimit
+        }) =>
+            dispatch({
+                type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete {name}?', {
+                        name: limit.name
+                    }),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        EntitlementPoolsActionHelper.deleteLimit(dispatch, {
+                            limit,
+                            entitlementPool: parent,
+                            licenseModelId,
+                            version
+                        }).then(
+                            () =>
+                                selectedLimit === limit.id &&
+                                onCloseLimitEditor()
+                        )
+                }
+            })
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(Limits);
index f1dc1f8..819fb7d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
-import EntitlementPoolsListEditorView, {generateConfirmationMsg} from './EntitlementPoolsListEditorView.jsx';
-import {actionTypes as globalMoadlActions}  from 'nfvo-components/modal/GlobalModalConstants.js';
+import EntitlementPoolsListEditorView, {
+    generateConfirmationMsg
+} from './EntitlementPoolsListEditorView.jsx';
+import { actionTypes as globalMoadlActions } from 'nfvo-components/modal/GlobalModalConstants.js';
 
-const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) => {
-
-       const {entitlementPoolsList} = entitlementPool;
-       const {data} = entitlementPool.entitlementPoolEditor;
-       const {vendorName} = licenseModelEditor.data;
-
-       return {
-               vendorName,
-               entitlementPoolsList,
-               isDisplayModal: Boolean(data),
-               isModalInEditMode: Boolean(data && data.id),
-       };
+const mapStateToProps = ({
+    licenseModel: { entitlementPool, licenseModelEditor }
+}) => {
+    const { entitlementPoolsList } = entitlementPool;
+    const { data } = entitlementPool.entitlementPoolEditor;
+    const { vendorName } = licenseModelEditor.data;
 
+    return {
+        vendorName,
+        entitlementPoolsList,
+        isDisplayModal: Boolean(data),
+        isModalInEditMode: Boolean(data && data.id)
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
-       return {
-               onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch),
-               onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool, licenseModelId, version}),
-               onDeleteEntitlementPool: entitlementPool => dispatch({
-                       type: globalMoadlActions.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: generateConfirmationMsg(entitlementPool),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: () => EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, {
-                                       licenseModelId,
-                                       entitlementPoolId: entitlementPool.id,
-                                       version
-                               })
-                       }
-               })
-       };
+const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onAddEntitlementPoolClick: () =>
+            EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch),
+        onEditEntitlementPoolClick: entitlementPool =>
+            EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {
+                entitlementPool,
+                licenseModelId,
+                version
+            }),
+        onDeleteEntitlementPool: entitlementPool =>
+            dispatch({
+                type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: generateConfirmationMsg(entitlementPool),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        EntitlementPoolsActionHelper.deleteEntitlementPool(
+                            dispatch,
+                            {
+                                licenseModelId,
+                                entitlementPoolId: entitlementPool.id,
+                                version
+                            }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsListEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    EntitlementPoolsListEditorView
+);
index cc0cda1..7a07f94 100644 (file)
@@ -22,120 +22,162 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 
 import EntitlementPoolsEditor from './EntitlementPoolsEditor.js';
-import {extractUnits} from './EntitlementPoolsConstants';
+import { extractUnits } from './EntitlementPoolsConstants';
 
 class EntitlementPoolsListEditorView extends React.Component {
-       static propTypes = {
-               vendorName: PropTypes.string,
-               licenseModelId: PropTypes.string.isRequired,
-               entitlementPoolsList: PropTypes.array,
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               isDisplayModal: PropTypes.bool,
-               isModalInEditMode: PropTypes.bool,
-               onAddEntitlementPoolClick: PropTypes.func,
-               onEditEntitlementPoolClick: PropTypes.func,
-               onDeleteEntitlementPool: PropTypes.func,
-       };
+    static propTypes = {
+        vendorName: PropTypes.string,
+        licenseModelId: PropTypes.string.isRequired,
+        entitlementPoolsList: PropTypes.array,
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        isDisplayModal: PropTypes.bool,
+        isModalInEditMode: PropTypes.bool,
+        onAddEntitlementPoolClick: PropTypes.func,
+        onEditEntitlementPoolClick: PropTypes.func,
+        onDeleteEntitlementPool: PropTypes.func
+    };
 
-       static defaultProps = {
-               entitlementPoolsList: []
-       };
+    static defaultProps = {
+        entitlementPoolsList: []
+    };
 
-       state = {
-               localFilter: ''
-       };
+    state = {
+        localFilter: ''
+    };
 
-       render() {
-               let {licenseModelId, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
-               let {onAddEntitlementPoolClick} = this.props;
-               const {localFilter} = this.state;
+    render() {
+        let {
+            licenseModelId,
+            isReadOnlyMode,
+            isDisplayModal,
+            isModalInEditMode,
+            version
+        } = this.props;
+        let { onAddEntitlementPoolClick } = this.props;
+        const { localFilter } = this.state;
 
-               return (
-                       <div className='license-model-list-editor entitlement-pools-list-editor'>
-                               <ListEditorView
-                                       title={i18n('Entitlement Pools')}
-                                       plusButtonTitle={i18n('Add Entitlement Pool')}
-                                       onAdd={onAddEntitlementPoolClick}
-                                       filterValue={localFilter}
-                                       onFilter={value => this.setState({localFilter: value})}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       {this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))}
-                               </ListEditorView>
-                               <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-modal entitlement-pools-modal'>
-                                       <Modal.Header>
-                                               <Modal.Title>{`${isModalInEditMode ? i18n('Edit Entitlement Pool') : i18n('Create New Entitlement Pool')}`}</Modal.Title>
-                                       </Modal.Header>
-                                       <Modal.Body>
-                                               {
-                                                       isDisplayModal && (
-                                                               <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
-                                                       )
-                                               }
-                                       </Modal.Body>
-                               </Modal>
-                       </div>
-               );
-       }
+        return (
+            <div className="license-model-list-editor entitlement-pools-list-editor">
+                <ListEditorView
+                    title={i18n('Entitlement Pools')}
+                    plusButtonTitle={i18n('Add Entitlement Pool')}
+                    onAdd={onAddEntitlementPoolClick}
+                    filterValue={localFilter}
+                    onFilter={value => this.setState({ localFilter: value })}
+                    isReadOnlyMode={isReadOnlyMode}>
+                    {this.filterList().map(entitlementPool =>
+                        this.renderEntitlementPoolListItem(
+                            entitlementPool,
+                            isReadOnlyMode
+                        )
+                    )}
+                </ListEditorView>
+                <Modal
+                    show={isDisplayModal}
+                    bsSize="large"
+                    animation={true}
+                    className="onborading-modal license-model-modal entitlement-pools-modal">
+                    <Modal.Header>
+                        <Modal.Title>{`${
+                            isModalInEditMode
+                                ? i18n('Edit Entitlement Pool')
+                                : i18n('Create New Entitlement Pool')
+                        }`}</Modal.Title>
+                    </Modal.Header>
+                    <Modal.Body>
+                        {isDisplayModal && (
+                            <EntitlementPoolsEditor
+                                version={version}
+                                licenseModelId={licenseModelId}
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    </Modal.Body>
+                </Modal>
+            </div>
+        );
+    }
 
-       filterList() {
-               let {entitlementPoolsList} = this.props;
-               let {localFilter} = this.state;
-               if(localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return entitlementPoolsList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return entitlementPoolsList;
-               }
-       }
+    filterList() {
+        let { entitlementPoolsList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return entitlementPoolsList.filter(
+                ({ name = '', description = '' }) => {
+                    return (
+                        escape(name).match(filter) ||
+                        escape(description).match(filter)
+                    );
+                }
+            );
+        } else {
+            return entitlementPoolsList;
+        }
+    }
 
-       renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode) {
-               let {id, name, description, thresholdValue, thresholdUnits} = entitlementPool;
-               let {onEditEntitlementPoolClick, onDeleteEntitlementPool} = this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               onSelect={() => onEditEntitlementPoolClick(entitlementPool)}
-                               onDelete={() => onDeleteEntitlementPool(entitlementPool)}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}>
-                               <div className='list-editor-item-view-field'>
+    renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode) {
+        let {
+            id,
+            name,
+            description,
+            thresholdValue,
+            thresholdUnits
+        } = entitlementPool;
+        let {
+            onEditEntitlementPoolClick,
+            onDeleteEntitlementPool
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                onSelect={() => onEditEntitlementPoolClick(entitlementPool)}
+                onDelete={() => onDeleteEntitlementPool(entitlementPool)}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div>
+                        <div className="textEllipses text name">{name}</div>
+                    </div>
+                </div>
 
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div ><div className='textEllipses text name'>{name}</div></div>
-                               </div>
-
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Entitlement')}</div>
-                                       <div className='entitlement-pools-count'>{thresholdValue && `${thresholdValue} ${extractUnits(thresholdUnits)}`}</div>
-                               </div>
-
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Description')}</div>
-                                       <div className='text description'>{description}</div>
-                               </div>
-                       </ListEditorItemView>
-               );
-       }
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Entitlement')}</div>
+                    <div className="entitlement-pools-count">
+                        {thresholdValue &&
+                            `${thresholdValue} ${extractUnits(thresholdUnits)}`}
+                    </div>
+                </div>
 
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Description')}</div>
+                    <div className="text description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
 }
 
 export default EntitlementPoolsListEditorView;
 
 export function generateConfirmationMsg(entitlementPoolToDelete) {
-       let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : '';
-       let msg = i18n('Are you sure you want to delete "{poolName}"?', {poolName: poolName});
-       let subMsg = entitlementPoolToDelete
-       && entitlementPoolToDelete.referencingFeatureGroups
-       && entitlementPoolToDelete.referencingFeatureGroups.length > 0 ?
-               i18n('This entitlement pool is associated with one or more feature groups') :
-               '';
-       return (
-               <div>
-                       <p>{msg}</p>
-                       <p>{subMsg}</p>
-               </div>
-       );
+    let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : '';
+    let msg = i18n('Are you sure you want to delete "{poolName}"?', {
+        poolName: poolName
+    });
+    let subMsg =
+        entitlementPoolToDelete &&
+        entitlementPoolToDelete.referencingFeatureGroups &&
+        entitlementPoolToDelete.referencingFeatureGroups.length > 0
+            ? i18n(
+                  'This entitlement pool is associated with one or more feature groups'
+              )
+            : '';
+    return (
+        <div>
+            <p>{msg}</p>
+            <p>{subMsg}</p>
+        </div>
+    );
 }
index fefd823..3c8621d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './EntitlementPoolsConstants';
+import { actionTypes } from './EntitlementPoolsConstants';
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.ENTITLEMENT_POOLS_LIST_LOADED:
-                       return [...action.response.results];
-               case actionTypes.ADD_ENTITLEMENT_POOL:
-                       return [...state, action.entitlementPool];
-               case actionTypes.EDIT_ENTITLEMENT_POOL:
-                       const indexForEdit = state.findIndex(entitlementPool => entitlementPool.id === action.entitlementPool.id);
-                       return [...state.slice(0, indexForEdit), action.entitlementPool, ...state.slice(indexForEdit + 1)];
-               case actionTypes.DELETE_ENTITLEMENT_POOL:
-                       return state.filter(entitlementPool => entitlementPool.id !== action.entitlementPoolId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.ENTITLEMENT_POOLS_LIST_LOADED:
+            return [...action.response.results];
+        case actionTypes.ADD_ENTITLEMENT_POOL:
+            return [...state, action.entitlementPool];
+        case actionTypes.EDIT_ENTITLEMENT_POOL:
+            const indexForEdit = state.findIndex(
+                entitlementPool =>
+                    entitlementPool.id === action.entitlementPool.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.entitlementPool,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.DELETE_ENTITLEMENT_POOL:
+            return state.filter(
+                entitlementPool =>
+                    entitlementPool.id !== action.entitlementPoolId
+            );
+        default:
+            return state;
+    }
 };
index 6edb1e1..997a6e0 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
 import FeatureGroupEditorView from './FeatureGroupEditorView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-export const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => {
-       let {entitlementPoolsList = []} = entitlementPool;
-       let {licenseKeyGroupsList = []} = licenseKeyGroup;
-       const {featureGroupEditor} = featureGroup;
-       let {data, selectedTab, genericFieldInfo, formReady} = featureGroupEditor;
-       const featureGroupId = data ? data.id : null;
-       const list = featureGroup.featureGroupsList;
+export const mapStateToProps = ({
+    licenseModel: { featureGroup, entitlementPool, licenseKeyGroup }
+}) => {
+    let { entitlementPoolsList = [] } = entitlementPool;
+    let { licenseKeyGroupsList = [] } = licenseKeyGroup;
+    const { featureGroupEditor } = featureGroup;
+    let { data, selectedTab, genericFieldInfo, formReady } = featureGroupEditor;
+    const featureGroupId = data ? data.id : null;
+    const list = featureGroup.featureGroupsList;
 
-       let previousData, FGNames = {}, isFormValid = true, invalidTabs = [];
+    let previousData,
+        FGNames = {},
+        isFormValid = true,
+        invalidTabs = [];
 
-       if (featureGroupId) {
-               previousData = list.find(featureGroup => featureGroup.id === featureGroupId);
-       }
+    if (featureGroupId) {
+        previousData = list.find(
+            featureGroup => featureGroup.id === featureGroupId
+        );
+    }
 
-       for (let i = 0; i < list.length; i++) {
-               FGNames[list[i].name.toLowerCase()] = list[i].id;
-       }
+    for (let i = 0; i < list.length; i++) {
+        FGNames[list[i].name.toLowerCase()] = list[i].id;
+    }
 
-       for (let field in genericFieldInfo) {
-               if (!genericFieldInfo[field].isValid) {
-                       isFormValid = false;
-                       let tabId = genericFieldInfo[field].tabId;
-                       if (invalidTabs.indexOf(tabId) === -1) {
-                               invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
-                       }
-               }
-       }
+    for (let field in genericFieldInfo) {
+        if (!genericFieldInfo[field].isValid) {
+            isFormValid = false;
+            let tabId = genericFieldInfo[field].tabId;
+            if (invalidTabs.indexOf(tabId) === -1) {
+                invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
+            }
+        }
+    }
 
-       return {
-               data,
-               previousData,
-               selectedTab,
-               entitlementPoolsList,
-               licenseKeyGroupsList,
-               isFormValid,
-               formReady,
-               genericFieldInfo,
-               invalidTabs,
-               FGNames
-       };
+    return {
+        data,
+        previousData,
+        selectedTab,
+        entitlementPoolsList,
+        licenseKeyGroupsList,
+        isFormValid,
+        formReady,
+        genericFieldInfo,
+        invalidTabs,
+        FGNames
+    };
 };
 
-
-const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onTabSelect: tab => FeatureGroupsActionHelper.selectEntitlementPoolsEditorTab(dispatch, {tab}),
-               onSubmit: (previousFeatureGroup, featureGroup) => {
-                       FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch);
-                       FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version});
-               },
-               onCancel: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch),
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
+const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onTabSelect: tab =>
+            FeatureGroupsActionHelper.selectEntitlementPoolsEditorTab(
+                dispatch,
+                {
+                    tab
+                }
+            ),
+        onSubmit: (previousFeatureGroup, featureGroup) => {
+            FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch);
+            FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {
+                licenseModelId,
+                previousFeatureGroup,
+                featureGroup,
+                version
+            });
+        },
+        onCancel: () =>
+            FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch),
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    FeatureGroupEditorView
+);
index 6d0acaa..fc82693 100644 (file)
@@ -19,211 +19,320 @@ import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
 import Tab from 'sdc-ui/lib/react/Tab.js';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {TabsForm as Form} from 'nfvo-components/input/validation/Form.jsx';
+import { TabsForm as Form } from 'nfvo-components/input/validation/Form.jsx';
 import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Validator from 'nfvo-utils/Validator.js';
 
-import {state as FeatureGroupStateConstants, FG_EDITOR_FORM} from './FeatureGroupsConstants.js';
+import {
+    state as FeatureGroupStateConstants,
+    FG_EDITOR_FORM
+} from './FeatureGroupsConstants.js';
 
 const FeatureGroupsPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       partNumber: PropTypes.string,
-       manufacturerReferenceNumber: PropTypes.string,
-       entitlementPoolsIds: PropTypes.arrayOf(PropTypes.string),
-       licenseKeyGroupsIds: PropTypes.arrayOf(PropTypes.string)
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    partNumber: PropTypes.string,
+    manufacturerReferenceNumber: PropTypes.string,
+    entitlementPoolsIds: PropTypes.arrayOf(PropTypes.string),
+    licenseKeyGroupsIds: PropTypes.arrayOf(PropTypes.string)
 });
 
-const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName}) => {
-       let {name, description, partNumber, manufacturerReferenceNumber} = data;
-       return (
-                       <GridSection hasLastColSet>
-                               <GridItem colSpan={2}>
-                                       <Input
-                                               groupClassName='field-section'
-                                               onChange={name => onDataChanged({name}, FG_EDITOR_FORM, {name: validateName})}
-                                               label={i18n('Name')}
-                                               data-test-id='create-fg-name'
-                                               value={name}
-                                               name='feature-group-name'
-                                               type='text'
-                                               isRequired={true}
-                                               isValid={genericFieldInfo.name.isValid}
-                                               errorText={genericFieldInfo.name.errorText} />
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow>
-                                       <Input
-                                               groupClassName='field-section'
-                                               className='description-field'
-                                               onChange={description => onDataChanged({description}, FG_EDITOR_FORM)}
-                                               data-test-id='create-fg-description'
-                                               label={i18n('Description')}
-                                               value={description}
-                                               name='feature-group-description'
-                                               type='textarea'
-                                               isValid={genericFieldInfo.description.isValid}
-                                               errorText={genericFieldInfo.description.errorText} />
-                               </GridItem>
-                               <GridItem colSpan={2}>
-                                       <Input
-                                               groupClassName='field-section'
-                                               onChange={partNumber => onDataChanged({partNumber}, FG_EDITOR_FORM)}
-                                               label={i18n('Part Number')}
-                                               data-test-id='create-fg-part-number'
-                                               value={partNumber}
-                                               isRequired={true}
-                                               type='text'
-                                               isValid={genericFieldInfo.partNumber.isValid}
-                                               errorText={genericFieldInfo.partNumber.errorText} />
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow>
-                                       <Input
-                                               groupClassName='field-section'
-                                               onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber}, FG_EDITOR_FORM)}
-                                               label={i18n('Manufacturer Reference Number')}
-                                               data-test-id='create-fg-reference-number'
-                                               value={manufacturerReferenceNumber}
-                                               isRequired={true}
-                                               type='text'
-                                               isValid={genericFieldInfo.manufacturerReferenceNumber.isValid}
-                                               errorText={genericFieldInfo.manufacturerReferenceNumber.errorText} />
-                               </GridItem>
-                       </GridSection>
-               );
+const GeneralTab = ({
+    data = {},
+    onDataChanged,
+    genericFieldInfo,
+    validateName
+}) => {
+    let { name, description, partNumber, manufacturerReferenceNumber } = data;
+    return (
+        <GridSection hasLastColSet>
+            <GridItem colSpan={2}>
+                <Input
+                    groupClassName="field-section"
+                    onChange={name =>
+                        onDataChanged({ name }, FG_EDITOR_FORM, {
+                            name: validateName
+                        })
+                    }
+                    label={i18n('Name')}
+                    data-test-id="create-fg-name"
+                    value={name}
+                    name="feature-group-name"
+                    type="text"
+                    isRequired={true}
+                    isValid={genericFieldInfo.name.isValid}
+                    errorText={genericFieldInfo.name.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <Input
+                    groupClassName="field-section"
+                    className="description-field"
+                    onChange={description =>
+                        onDataChanged({ description }, FG_EDITOR_FORM)
+                    }
+                    data-test-id="create-fg-description"
+                    label={i18n('Description')}
+                    value={description}
+                    name="feature-group-description"
+                    type="textarea"
+                    isValid={genericFieldInfo.description.isValid}
+                    errorText={genericFieldInfo.description.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2}>
+                <Input
+                    groupClassName="field-section"
+                    onChange={partNumber =>
+                        onDataChanged({ partNumber }, FG_EDITOR_FORM)
+                    }
+                    label={i18n('Part Number')}
+                    data-test-id="create-fg-part-number"
+                    value={partNumber}
+                    isRequired={true}
+                    type="text"
+                    isValid={genericFieldInfo.partNumber.isValid}
+                    errorText={genericFieldInfo.partNumber.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <Input
+                    groupClassName="field-section"
+                    onChange={manufacturerReferenceNumber =>
+                        onDataChanged(
+                            { manufacturerReferenceNumber },
+                            FG_EDITOR_FORM
+                        )
+                    }
+                    label={i18n('Manufacturer Reference Number')}
+                    data-test-id="create-fg-reference-number"
+                    value={manufacturerReferenceNumber}
+                    isRequired={true}
+                    type="text"
+                    isValid={
+                        genericFieldInfo.manufacturerReferenceNumber.isValid
+                    }
+                    errorText={
+                        genericFieldInfo.manufacturerReferenceNumber.errorText
+                    }
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
-const EntitlementPoolsTab = ({entitlementPoolsList, data, onDataChanged, isReadOnlyMode}) => {
-       const dualBoxFilterTitle = {
-               left: i18n('Available Entitlement Pools'),
-               right: i18n('Selected Entitlement Pools')
-       };
-       if (entitlementPoolsList.length > 0) {
-               return (
-                       <DualListboxView
-                               isReadOnlyMode={isReadOnlyMode}
-                               filterTitle={dualBoxFilterTitle}
-                               selectedValuesList={data.entitlementPoolsIds}
-                               availableList={entitlementPoolsList}
-                               onChange={ selectedValuesList => onDataChanged( { entitlementPoolsIds: selectedValuesList }, FG_EDITOR_FORM )}/>
-               );
-       } else {
-               return (
-                       <p>{i18n('There are no available entitlement pools')}</p>
-               );
-       }
+const EntitlementPoolsTab = ({
+    entitlementPoolsList,
+    data,
+    onDataChanged,
+    isReadOnlyMode
+}) => {
+    const dualBoxFilterTitle = {
+        left: i18n('Available Entitlement Pools'),
+        right: i18n('Selected Entitlement Pools')
+    };
+    if (entitlementPoolsList.length > 0) {
+        return (
+            <DualListboxView
+                isReadOnlyMode={isReadOnlyMode}
+                filterTitle={dualBoxFilterTitle}
+                selectedValuesList={data.entitlementPoolsIds}
+                availableList={entitlementPoolsList}
+                onChange={selectedValuesList =>
+                    onDataChanged(
+                        { entitlementPoolsIds: selectedValuesList },
+                        FG_EDITOR_FORM
+                    )
+                }
+            />
+        );
+    } else {
+        return <p>{i18n('There are no available entitlement pools')}</p>;
+    }
 };
 
-const LKGTab = ({licenseKeyGroupsList, data, onDataChanged, isReadOnlyMode}) => {
-       const dualBoxFilterTitle = {
-               left: i18n('Available License Key Groups'),
-               right: i18n('Selected License Key Groups')
-       };
-       if (licenseKeyGroupsList.length > 0) {
-               return (
-                       <DualListboxView
-                               isReadOnlyMode={isReadOnlyMode}
-                               filterTitle={dualBoxFilterTitle}
-                               selectedValuesList={data.licenseKeyGroupsIds}
-                               availableList={licenseKeyGroupsList}
-                               onChange={ selectedValuesList => onDataChanged( { licenseKeyGroupsIds: selectedValuesList }, FG_EDITOR_FORM )}/>
-               );
-       } else {
-               return (
-                       <p>{i18n('There are no available license key groups')}</p>
-               );
-       }
+const LKGTab = ({
+    licenseKeyGroupsList,
+    data,
+    onDataChanged,
+    isReadOnlyMode
+}) => {
+    const dualBoxFilterTitle = {
+        left: i18n('Available License Key Groups'),
+        right: i18n('Selected License Key Groups')
+    };
+    if (licenseKeyGroupsList.length > 0) {
+        return (
+            <DualListboxView
+                isReadOnlyMode={isReadOnlyMode}
+                filterTitle={dualBoxFilterTitle}
+                selectedValuesList={data.licenseKeyGroupsIds}
+                availableList={licenseKeyGroupsList}
+                onChange={selectedValuesList =>
+                    onDataChanged(
+                        { licenseKeyGroupsIds: selectedValuesList },
+                        FG_EDITOR_FORM
+                    )
+                }
+            />
+        );
+    } else {
+        return <p>{i18n('There are no available license key groups')}</p>;
+    }
 };
 
 class FeatureGroupEditorView extends React.Component {
+    static propTypes = {
+        data: FeatureGroupsPropType,
+        previousData: FeatureGroupsPropType,
+        isReadOnlyMode: PropTypes.bool,
+        FGNames: PropTypes.object,
 
+        onSubmit: PropTypes.func,
+        onCancel: PropTypes.func,
 
-       static propTypes = {
-               data: FeatureGroupsPropType,
-               previousData: FeatureGroupsPropType,
-               isReadOnlyMode: PropTypes.bool,
-               FGNames: PropTypes.object,
-
-               onSubmit: PropTypes.func,
-               onCancel: PropTypes.func,
-
-               selectedTab: PropTypes.number,
-               onTabSelect: PropTypes.func,
-
-               entitlementPoolsList: DualListboxView.propTypes.availableList,
-               licenseKeyGroupsList: DualListboxView.propTypes.availableList
-       };
-
-
-       static defaultProps = {
-               data: {},
-               selectedTab: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL,
-       };
-
-       state = {
-               localEntitlementPoolsListFilter: '',
-               localLicenseKeyGroupsListFilter: ''
-       };
-
-
-       render() {
-               let {selectedTab, onTabSelect, isReadOnlyMode, invalidTabs, data, onDataChanged, genericFieldInfo, entitlementPoolsList, licenseKeyGroupsList} = this.props;
-               return (
-                       <div>
-                       { genericFieldInfo && <Form
-                               ref='validationForm'
-                               hasButtons={true}
-                               onSubmit={ () => this.submit() }
-                               isValid={this.props.isFormValid}
-                               formReady={this.props.formReady}
-                               onValidateForm={() => this.props.onValidateForm(FG_EDITOR_FORM) }
-                               onReset={ () => this.props.onCancel() }
-                               labledButtons={true}
-                               isReadOnlyMode={isReadOnlyMode}
-                               name='feature-group-validation-form'
-                               className='license-model-form feature-group-form'>
-                               <Tabs activeTab={onTabSelect ? selectedTab : undefined} onTabClick={onTabSelect} invalidTabs={invalidTabs} id='vlmFGValTabs' >
-                                       <Tab tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')}  >
-                                               <fieldset disabled={isReadOnlyMode}>
-                                                       <GeneralTab data={data} onDataChanged={onDataChanged} genericFieldInfo={genericFieldInfo}  validateName={(value)=> this.validateName(value)}/>
-                                               </fieldset>
-                                       </Tab>
-                                       <Tab
-                                               tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
-                                               title={i18n('Entitlement Pools')} >
-                                               <fieldset disabled={isReadOnlyMode}>
-                                                       <EntitlementPoolsTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} entitlementPoolsList={entitlementPoolsList} />
-                                               </fieldset>
-                                       </Tab>
-                                       <Tab
-                                               tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENSE_KEY_GROUPS}
-                                               title={i18n('License Key Groups')} >
-                                               <fieldset disabled={isReadOnlyMode}>
-                                                       <LKGTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} licenseKeyGroupsList={licenseKeyGroupsList} />
-                                               </fieldset>
-                                       </Tab>
-                               </Tabs>
-
-                               </Form> }
-                       </div>
-               );
-       }
-
-       submit() {
-               const {data: featureGroup, previousData: previousFeatureGroup} = this.props;
-               this.props.onSubmit(previousFeatureGroup, featureGroup);
-       }
-
-       validateName(value) {
-               const {data: {id}, FGNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: FGNames});
-
-               return !isExists ?  {isValid: true, errorText: ''} :
-                       {isValid: false, errorText: i18n('Feature group by the name \'' + value + '\' already exists. Feature group name must be unique')};
-       }
-}
+        selectedTab: PropTypes.number,
+        onTabSelect: PropTypes.func,
+
+        entitlementPoolsList: DualListboxView.propTypes.availableList,
+        licenseKeyGroupsList: DualListboxView.propTypes.availableList
+    };
+
+    static defaultProps = {
+        data: {},
+        selectedTab:
+            FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
+    };
+
+    state = {
+        localEntitlementPoolsListFilter: '',
+        localLicenseKeyGroupsListFilter: ''
+    };
 
+    render() {
+        let {
+            selectedTab,
+            onTabSelect,
+            isReadOnlyMode,
+            invalidTabs,
+            data,
+            onDataChanged,
+            genericFieldInfo,
+            entitlementPoolsList,
+            licenseKeyGroupsList
+        } = this.props;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() =>
+                            this.props.onValidateForm(FG_EDITOR_FORM)
+                        }
+                        onReset={() => this.props.onCancel()}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        name="feature-group-validation-form"
+                        className="license-model-form feature-group-form">
+                        <Tabs
+                            activeTab={onTabSelect ? selectedTab : undefined}
+                            onTabClick={onTabSelect}
+                            invalidTabs={invalidTabs}
+                            id="vlmFGValTabs">
+                            <Tab
+                                tabId={
+                                    FeatureGroupStateConstants
+                                        .SELECTED_FEATURE_GROUP_TAB.GENERAL
+                                }
+                                title={i18n('General')}>
+                                <fieldset disabled={isReadOnlyMode}>
+                                    <GeneralTab
+                                        data={data}
+                                        onDataChanged={onDataChanged}
+                                        genericFieldInfo={genericFieldInfo}
+                                        validateName={value =>
+                                            this.validateName(value)
+                                        }
+                                    />
+                                </fieldset>
+                            </Tab>
+                            <Tab
+                                tabId={
+                                    FeatureGroupStateConstants
+                                        .SELECTED_FEATURE_GROUP_TAB
+                                        .ENTITLEMENT_POOLS
+                                }
+                                title={i18n('Entitlement Pools')}>
+                                <fieldset disabled={isReadOnlyMode}>
+                                    <EntitlementPoolsTab
+                                        isReadOnlyMode={isReadOnlyMode}
+                                        data={data}
+                                        onDataChanged={onDataChanged}
+                                        entitlementPoolsList={
+                                            entitlementPoolsList
+                                        }
+                                    />
+                                </fieldset>
+                            </Tab>
+                            <Tab
+                                tabId={
+                                    FeatureGroupStateConstants
+                                        .SELECTED_FEATURE_GROUP_TAB
+                                        .LICENSE_KEY_GROUPS
+                                }
+                                title={i18n('License Key Groups')}>
+                                <fieldset disabled={isReadOnlyMode}>
+                                    <LKGTab
+                                        isReadOnlyMode={isReadOnlyMode}
+                                        data={data}
+                                        onDataChanged={onDataChanged}
+                                        licenseKeyGroupsList={
+                                            licenseKeyGroupsList
+                                        }
+                                    />
+                                </fieldset>
+                            </Tab>
+                        </Tabs>
+                    </Form>
+                )}
+            </div>
+        );
+    }
+
+    submit() {
+        const {
+            data: featureGroup,
+            previousData: previousFeatureGroup
+        } = this.props;
+        this.props.onSubmit(previousFeatureGroup, featureGroup);
+    }
+
+    validateName(value) {
+        const { data: { id }, FGNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: FGNames
+        });
+
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "Feature group by the name '" +
+                          value +
+                          "' already exists. Feature group name must be unique"
+                  )
+              };
+    }
+}
 
 export default FeatureGroupEditorView;
index 2692548..55e2710 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
-import FeatureGroupsActionHelper  from './FeatureGroupsActionHelper.js';
-import FeatureGroupListEditorView, {generateConfirmationMsg} from './FeatureGroupListEditorView.jsx';
+import { connect } from 'react-redux';
+import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
+import FeatureGroupListEditorView, {
+    generateConfirmationMsg
+} from './FeatureGroupListEditorView.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as globalMoadlActions}  from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as globalMoadlActions } from 'nfvo-components/modal/GlobalModalConstants.js';
 
-export const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => {
-
-       const {featureGroupEditor: {data}, featureGroupsList} = featureGroup;
-       const {vendorName, version} = licenseModelEditor.data;
-
-       return {
-               vendorName,
-               version,
-               featureGroupsModal: {
-                       show: Boolean(data),
-                       editMode: Boolean(data && data.id)
-               },
-               featureGroupsList
-       };
+export const mapStateToProps = ({
+    licenseModel: { featureGroup, licenseModelEditor }
+}) => {
+    const { featureGroupEditor: { data }, featureGroupsList } = featureGroup;
+    const { vendorName, version } = licenseModelEditor.data;
 
+    return {
+        vendorName,
+        version,
+        featureGroupsModal: {
+            show: Boolean(data),
+            editMode: Boolean(data && data.id)
+        },
+        featureGroupsList
+    };
 };
 
-
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
-       return {
-               onDeleteFeatureGroupClick: (featureGroup, version) => dispatch({
-                       type: globalMoadlActions.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: generateConfirmationMsg(featureGroup),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=>FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroup.id, licenseModelId, version})
-                       }
-               }),
-               onAddFeatureGroupClick: (actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version: actualVersion}),
-               onEditFeatureGroupClick: (featureGroup, actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
-                       featureGroup,
-                       licenseModelId,
-                       version: actualVersion
-               })
-       };
+const mapActionsToProps = (dispatch, { licenseModelId }) => {
+    return {
+        onDeleteFeatureGroupClick: (featureGroup, version) =>
+            dispatch({
+                type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: generateConfirmationMsg(featureGroup),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {
+                            featureGroupId: featureGroup.id,
+                            licenseModelId,
+                            version
+                        })
+                }
+            }),
+        onAddFeatureGroupClick: actualVersion =>
+            FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
+                licenseModelId,
+                version: actualVersion
+            }),
+        onEditFeatureGroupClick: (featureGroup, actualVersion) =>
+            FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
+                featureGroup,
+                licenseModelId,
+                version: actualVersion
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupListEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    FeatureGroupListEditorView
+);
index f59e000..91f77b3 100644 (file)
@@ -24,147 +24,184 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js
 import FeatureGroupEditor from './FeatureGroupEditor.js';
 
 class FeatureGroupListEditorView extends React.Component {
-       static propTypes = {
-               vendorName: PropTypes.string,
-               licenseModelId: PropTypes.string.isRequired,
-               featureGroupsModal: PropTypes.shape({
-                       show: PropTypes.bool,
-                       editMode: PropTypes.bool
-               }),
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               onAddFeatureGroupClick: PropTypes.func,
-               onEditFeatureGroupClick: PropTypes.func,
-               onDeleteFeatureGroupClick: PropTypes.func,
-               onCancelFeatureGroupsEditor: PropTypes.func,
-               featureGroupsList: PropTypes.array
-       };
-
-       static defaultProps = {
-               featureGroupsList: [],
-               featureGroupsModal: {
-                       show: false,
-                       editMode: false
-               }
-       };
-
-       state = {
-               localFilter: ''
-       };
-
-       render() {
-               let {licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick, version} = this.props;
-               const {localFilter} = this.state;
-               return (
-                       <div className='license-model-list-editor feature-groups-list-editor'>
-                               <ListEditorView
-                                       title={i18n('Feature Groups')}
-                                       plusButtonTitle={i18n('Add Feature Group')}
-                                       filterValue={localFilter}
-                                       onFilter={value => this.setState({localFilter: value})}
-                                       onAdd={() => onAddFeatureGroupClick(version)}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       {this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode, version))}
-                               </ListEditorView>
-                               {featureGroupsModal.show && <Modal show={featureGroupsModal.show} bsSize='large' animation={true}
-                                              className='onborading-modal license-model-modal feature-group-modal'>
-                                               <Modal.Header>
-                                                       <Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title>
-                                               </Modal.Header>
-                                               <Modal.Body>
-                                                       <FeatureGroupEditor
-                                                               version={version}
-                                                               licenseModelId={licenseModelId}
-                                                               isReadOnlyMode={isReadOnlyMode}/>
-                                               </Modal.Body>
-                                       </Modal>
-                               }
-
-                       </div>
-               );
-       }
-
-
-       renderFeatureGroupListItem(listItem, isReadOnlyMode, version) {
-               let {name, description, manufacturerReferenceNumber, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem;
-               return (
-                       <ListEditorItemView
-                               key={listItem.id}
-                               onDelete={() => this.deleteFeatureGroupItem(listItem, version)}
-                               onSelect={() => this.editFeatureGroupItem(listItem, version)}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div className='text name'>{name}</div>
-                               </div>
-
-                               <div className='list-editor-item-view-field smaller-field'>
-                                       <div className='feature-groups-count-field'>
-                                               <div className='title'>{i18n('EP')}</div>
-                                               <div className='feature-groups-count-ep'>{entitlementPoolsIds.length || 0}</div>
-                                       </div>
-                               </div>
-                               <div className='list-editor-item-view-field smaller-field'>
-                                       <div className='feature-groups-count-field'>
-                                               <div className='title'>{i18n('LKG')}</div>
-                                               <div className='feature-groups-count-lk'>{licenseKeyGroupsIds.length || 0}</div>
-                                       </div>
-                               </div>
-
-                               <div className='list-editor-item-view-field'>
-                                       <div className='feature-groups-count-field'>
-                                               <div className='title title-no-wrap'>{i18n('Manufacturer Reference Number')}</div>
-                                               <div className='feature-groups-mrn-ep'>{manufacturerReferenceNumber}</div>
-                                       </div>
-                               </div>
-
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Description')}</div>
-                                       <div className='text description'>{description}</div>
-                               </div>
-
-
-
-                       </ListEditorItemView>
-               );
-       }
-
-       filterList() {
-               let {featureGroupsList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return featureGroupsList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return featureGroupsList;
-               }
-       }
-
-       editFeatureGroupItem(featureGroup, version) {
-               this.props.onEditFeatureGroupClick(featureGroup, version);
-       }
-
-       deleteFeatureGroupItem(featureGroup, version) {
-               this.props.onDeleteFeatureGroupClick(featureGroup, version);
-       }
+    static propTypes = {
+        vendorName: PropTypes.string,
+        licenseModelId: PropTypes.string.isRequired,
+        featureGroupsModal: PropTypes.shape({
+            show: PropTypes.bool,
+            editMode: PropTypes.bool
+        }),
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        onAddFeatureGroupClick: PropTypes.func,
+        onEditFeatureGroupClick: PropTypes.func,
+        onDeleteFeatureGroupClick: PropTypes.func,
+        onCancelFeatureGroupsEditor: PropTypes.func,
+        featureGroupsList: PropTypes.array
+    };
+
+    static defaultProps = {
+        featureGroupsList: [],
+        featureGroupsModal: {
+            show: false,
+            editMode: false
+        }
+    };
+
+    state = {
+        localFilter: ''
+    };
+
+    render() {
+        let {
+            licenseModelId,
+            featureGroupsModal,
+            isReadOnlyMode,
+            onAddFeatureGroupClick,
+            version
+        } = this.props;
+        const { localFilter } = this.state;
+        return (
+            <div className="license-model-list-editor feature-groups-list-editor">
+                <ListEditorView
+                    title={i18n('Feature Groups')}
+                    plusButtonTitle={i18n('Add Feature Group')}
+                    filterValue={localFilter}
+                    onFilter={value => this.setState({ localFilter: value })}
+                    onAdd={() => onAddFeatureGroupClick(version)}
+                    isReadOnlyMode={isReadOnlyMode}>
+                    {this.filterList().map(listItem =>
+                        this.renderFeatureGroupListItem(
+                            listItem,
+                            isReadOnlyMode,
+                            version
+                        )
+                    )}
+                </ListEditorView>
+                {featureGroupsModal.show && (
+                    <Modal
+                        show={featureGroupsModal.show}
+                        bsSize="large"
+                        animation={true}
+                        className="onborading-modal license-model-modal feature-group-modal">
+                        <Modal.Header>
+                            <Modal.Title>{`${
+                                featureGroupsModal.editMode
+                                    ? i18n('Edit Feature Group')
+                                    : i18n('Create New Feature Group')
+                            }`}</Modal.Title>
+                        </Modal.Header>
+                        <Modal.Body>
+                            <FeatureGroupEditor
+                                version={version}
+                                licenseModelId={licenseModelId}
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        </Modal.Body>
+                    </Modal>
+                )}
+            </div>
+        );
+    }
+
+    renderFeatureGroupListItem(listItem, isReadOnlyMode, version) {
+        let {
+            name,
+            description,
+            manufacturerReferenceNumber,
+            entitlementPoolsIds = [],
+            licenseKeyGroupsIds = []
+        } = listItem;
+        return (
+            <ListEditorItemView
+                key={listItem.id}
+                onDelete={() => this.deleteFeatureGroupItem(listItem, version)}
+                onSelect={() => this.editFeatureGroupItem(listItem, version)}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div className="text name">{name}</div>
+                </div>
+
+                <div className="list-editor-item-view-field smaller-field">
+                    <div className="feature-groups-count-field">
+                        <div className="title">{i18n('EP')}</div>
+                        <div className="feature-groups-count-ep">
+                            {entitlementPoolsIds.length || 0}
+                        </div>
+                    </div>
+                </div>
+                <div className="list-editor-item-view-field smaller-field">
+                    <div className="feature-groups-count-field">
+                        <div className="title">{i18n('LKG')}</div>
+                        <div className="feature-groups-count-lk">
+                            {licenseKeyGroupsIds.length || 0}
+                        </div>
+                    </div>
+                </div>
+
+                <div className="list-editor-item-view-field">
+                    <div className="feature-groups-count-field">
+                        <div className="title title-no-wrap">
+                            {i18n('Manufacturer Reference Number')}
+                        </div>
+                        <div className="feature-groups-mrn-ep">
+                            {manufacturerReferenceNumber}
+                        </div>
+                    </div>
+                </div>
+
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Description')}</div>
+                    <div className="text description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
+
+    filterList() {
+        let { featureGroupsList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return featureGroupsList.filter(
+                ({ name = '', description = '' }) => {
+                    return (
+                        escape(name).match(filter) ||
+                        escape(description).match(filter)
+                    );
+                }
+            );
+        } else {
+            return featureGroupsList;
+        }
+    }
+
+    editFeatureGroupItem(featureGroup, version) {
+        this.props.onEditFeatureGroupClick(featureGroup, version);
+    }
+
+    deleteFeatureGroupItem(featureGroup, version) {
+        this.props.onDeleteFeatureGroupClick(featureGroup, version);
+    }
 }
 
 export default FeatureGroupListEditorView;
 
 export function generateConfirmationMsg(featureGroupToDelete) {
-       let name = featureGroupToDelete ? featureGroupToDelete.name : '';
-       let msg = i18n('Are you sure you want to delete "{name}"?', {name: name});
-       let subMsg = featureGroupToDelete.referencingLicenseAgreements
-       && featureGroupToDelete.referencingLicenseAgreements.length > 0 ?
-               i18n('This feature group is associated with one ore more license agreements') :
-               '';
-       return (
-               <div>
-                       <p>{msg}</p>
-                       <p>{subMsg}</p>
-               </div>
-       );
+    let name = featureGroupToDelete ? featureGroupToDelete.name : '';
+    let msg = i18n('Are you sure you want to delete "{name}"?', { name: name });
+    let subMsg =
+        featureGroupToDelete.referencingLicenseAgreements &&
+        featureGroupToDelete.referencingLicenseAgreements.length > 0
+            ? i18n(
+                  'This feature group is associated with one ore more license agreements'
+              )
+            : '';
+    return (
+        <div>
+            <p>{msg}</p>
+            <p>{subMsg}</p>
+        </div>
+    );
 }
index 9e7fe8e..22e21a6 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes as featureGroupsActionConstants} from './FeatureGroupsConstants.js';
+import { actionTypes as featureGroupsActionConstants } from './FeatureGroupsConstants.js';
 import EntitlementPoolsActionHelper from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
 import LicenseKeyGroupsActionHelper from 'sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 function baseUrl(licenseModelId, version) {
-       const restPrefix = Configuration.get('restPrefix');
-       const {id: versionId} = version;
-       return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/feature-groups`;
+    const restPrefix = Configuration.get('restPrefix');
+    const { id: versionId } = version;
+    return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/feature-groups`;
 }
 
 function fetchFeatureGroup(licenseModelId, featureGroupId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${featureGroupId}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl(licenseModelId, version)}/${featureGroupId}`
+    );
 }
 
 function fetchFeatureGroupsList(licenseModelId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
 }
 
 function deleteFeatureGroup(licenseModelId, featureGroupId, version) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${featureGroupId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(licenseModelId, version)}/${featureGroupId}`
+    );
 }
 
 function addFeatureGroup(licenseModelId, featureGroup, version) {
-       return RestAPIUtil.post(baseUrl(licenseModelId, version), {
-               name: featureGroup.name,
-               description: featureGroup.description,
-               partNumber: featureGroup.partNumber,
-               manufacturerReferenceNumber: featureGroup.manufacturerReferenceNumber,
-               addedLicenseKeyGroupsIds: featureGroup.licenseKeyGroupsIds,
-               addedEntitlementPoolsIds: featureGroup.entitlementPoolsIds
-       });
+    return RestAPIUtil.post(baseUrl(licenseModelId, version), {
+        name: featureGroup.name,
+        description: featureGroup.description,
+        partNumber: featureGroup.partNumber,
+        manufacturerReferenceNumber: featureGroup.manufacturerReferenceNumber,
+        addedLicenseKeyGroupsIds: featureGroup.licenseKeyGroupsIds,
+        addedEntitlementPoolsIds: featureGroup.entitlementPoolsIds
+    });
 }
 
-function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version) {
-
-       const {licenseKeyGroupsIds = []} = featureGroup;
-       const {licenseKeyGroupsIds: prevLicenseKeyGroupsIds = []} = previousFeatureGroup;
-       const {entitlementPoolsIds = []} = featureGroup;
-       const {entitlementPoolsIds: prevEntitlementPoolsIds = []} = previousFeatureGroup;
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${featureGroup.id}`, {
-               name: featureGroup.name,
-               description: featureGroup.description,
-               partNumber: featureGroup.partNumber,
-               manufacturerReferenceNumber: featureGroup.manufacturerReferenceNumber,
-               addedLicenseKeyGroupsIds: licenseKeyGroupsIds.filter(licenseKeyGroupId => prevLicenseKeyGroupsIds.indexOf(licenseKeyGroupId) === -1),
-               removedLicenseKeyGroupsIds: prevLicenseKeyGroupsIds.filter(prevLicenseKeyGroupId => licenseKeyGroupsIds.indexOf(prevLicenseKeyGroupId) === -1),
-               addedEntitlementPoolsIds: entitlementPoolsIds.filter(entitlementPoolId => prevEntitlementPoolsIds.indexOf(entitlementPoolId) === -1),
-               removedEntitlementPoolsIds: prevEntitlementPoolsIds.filter(prevEntitlementPoolId => entitlementPoolsIds.indexOf(prevEntitlementPoolId) === -1)
-
-       });
+function updateFeatureGroup(
+    licenseModelId,
+    previousFeatureGroup,
+    featureGroup,
+    version
+) {
+    const { licenseKeyGroupsIds = [] } = featureGroup;
+    const {
+        licenseKeyGroupsIds: prevLicenseKeyGroupsIds = []
+    } = previousFeatureGroup;
+    const { entitlementPoolsIds = [] } = featureGroup;
+    const {
+        entitlementPoolsIds: prevEntitlementPoolsIds = []
+    } = previousFeatureGroup;
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${featureGroup.id}`,
+        {
+            name: featureGroup.name,
+            description: featureGroup.description,
+            partNumber: featureGroup.partNumber,
+            manufacturerReferenceNumber:
+                featureGroup.manufacturerReferenceNumber,
+            addedLicenseKeyGroupsIds: licenseKeyGroupsIds.filter(
+                licenseKeyGroupId =>
+                    prevLicenseKeyGroupsIds.indexOf(licenseKeyGroupId) === -1
+            ),
+            removedLicenseKeyGroupsIds: prevLicenseKeyGroupsIds.filter(
+                prevLicenseKeyGroupId =>
+                    licenseKeyGroupsIds.indexOf(prevLicenseKeyGroupId) === -1
+            ),
+            addedEntitlementPoolsIds: entitlementPoolsIds.filter(
+                entitlementPoolId =>
+                    prevEntitlementPoolsIds.indexOf(entitlementPoolId) === -1
+            ),
+            removedEntitlementPoolsIds: prevEntitlementPoolsIds.filter(
+                prevEntitlementPoolId =>
+                    entitlementPoolsIds.indexOf(prevEntitlementPoolId) === -1
+            )
+        }
+    );
 }
 
 export default {
-       fetchFeatureGroup(dispatch, {licenseModelId, featureGroupId, version}) {
-               return fetchFeatureGroup(licenseModelId, featureGroupId, version);
-       },
+    fetchFeatureGroup(dispatch, { licenseModelId, featureGroupId, version }) {
+        return fetchFeatureGroup(licenseModelId, featureGroupId, version);
+    },
 
-       fetchFeatureGroupsList(dispatch, {licenseModelId, version}) {
-               return fetchFeatureGroupsList(licenseModelId, version).then(response => dispatch({
-                       type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
-                       response
-               }));
-       },
+    fetchFeatureGroupsList(dispatch, { licenseModelId, version }) {
+        return fetchFeatureGroupsList(licenseModelId, version).then(response =>
+            dispatch({
+                type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
+                response
+            })
+        );
+    },
 
-       deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId, version}) {
-               return deleteFeatureGroup(licenseModelId, featureGroupId, version).then(() => {
-                       dispatch({
-                               type: featureGroupsActionConstants.DELETE_FEATURE_GROUPS,
-                               featureGroupId
-                       });
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
+    deleteFeatureGroup(dispatch, { licenseModelId, featureGroupId, version }) {
+        return deleteFeatureGroup(licenseModelId, featureGroupId, version).then(
+            () => {
+                dispatch({
+                    type: featureGroupsActionConstants.DELETE_FEATURE_GROUPS,
+                    featureGroupId
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            }
+        );
+    },
 
-       saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version}) {
-               if (previousFeatureGroup) {
-                       return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version).then(() =>{
-                               dispatch({
-                                       type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS,
-                                       featureGroup
-                               });
-                               EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
-                               LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-               else {
-                       return addFeatureGroup(licenseModelId, featureGroup, version).then(response => {
-                               dispatch({
-                                       type: featureGroupsActionConstants.ADD_FEATURE_GROUPS,
-                                       featureGroup: {
-                                               ...featureGroup,
-                                               id: response.value,
-                                               referencingLicenseAgreements: []
-                                       }
-                               });
-                               EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
-                               LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-       },
+    saveFeatureGroup(
+        dispatch,
+        { licenseModelId, previousFeatureGroup, featureGroup, version }
+    ) {
+        if (previousFeatureGroup) {
+            return updateFeatureGroup(
+                licenseModelId,
+                previousFeatureGroup,
+                featureGroup,
+                version
+            ).then(() => {
+                dispatch({
+                    type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS,
+                    featureGroup
+                });
+                EntitlementPoolsActionHelper.fetchEntitlementPoolsList(
+                    dispatch,
+                    { licenseModelId, version }
+                );
+                LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(
+                    dispatch,
+                    { licenseModelId, version }
+                );
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        } else {
+            return addFeatureGroup(licenseModelId, featureGroup, version).then(
+                response => {
+                    dispatch({
+                        type: featureGroupsActionConstants.ADD_FEATURE_GROUPS,
+                        featureGroup: {
+                            ...featureGroup,
+                            id: response.value,
+                            referencingLicenseAgreements: []
+                        }
+                    });
+                    EntitlementPoolsActionHelper.fetchEntitlementPoolsList(
+                        dispatch,
+                        { licenseModelId, version }
+                    );
+                    LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(
+                        dispatch,
+                        { licenseModelId, version }
+                    );
+                    return ItemsHelper.checkItemStatus(dispatch, {
+                        itemId: licenseModelId,
+                        versionId: version.id
+                    });
+                }
+            );
+        }
+    },
 
-       selectEntitlementPoolsEditorTab(dispatch, {tab}) {
-               dispatch({
-                       type: featureGroupsActionConstants.featureGroupsEditor.SELECT_TAB,
-                       tab
-               });
-       },
+    selectEntitlementPoolsEditorTab(dispatch, { tab }) {
+        dispatch({
+            type: featureGroupsActionConstants.featureGroupsEditor.SELECT_TAB,
+            tab
+        });
+    },
 
-       openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId, version}) {
-               return Promise.all([
-                       EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}),
-                       LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version})
-               ]).then(() => {
-                       dispatch({
-                               type: featureGroupsActionConstants.featureGroupsEditor.OPEN,
-                               featureGroup
-                       });
-               });
-       },
+    openFeatureGroupsEditor(
+        dispatch,
+        { featureGroup, licenseModelId, version }
+    ) {
+        return Promise.all([
+            EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {
+                licenseModelId,
+                version
+            }),
+            LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {
+                licenseModelId,
+                version
+            })
+        ]).then(() => {
+            dispatch({
+                type: featureGroupsActionConstants.featureGroupsEditor.OPEN,
+                featureGroup
+            });
+        });
+    },
 
-       closeFeatureGroupsEditor(dispatch) {
-               dispatch({
-                       type: featureGroupsActionConstants.featureGroupsEditor.CLOSE
-               });
-       }
+    closeFeatureGroupsEditor(dispatch) {
+        dispatch({
+            type: featureGroupsActionConstants.featureGroupsEditor.CLOSE
+        });
+    }
 };
index 4c5a94f..feeb5b6 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       FEATURE_GROUPS_LIST_LOADED: null,
-       ADD_FEATURE_GROUPS: null,
-       EDIT_FEATURE_GROUPS: null,
-       DELETE_FEATURE_GROUPS: null,
+    FEATURE_GROUPS_LIST_LOADED: null,
+    ADD_FEATURE_GROUPS: null,
+    EDIT_FEATURE_GROUPS: null,
+    DELETE_FEATURE_GROUPS: null,
 
-       ENTITLEMENT_POOLS_LIST_LOADED: null,
+    ENTITLEMENT_POOLS_LIST_LOADED: null,
 
-       featureGroupsEditor: {
-               OPEN: null,
-               CLOSE: null,
-               DATA_CHANGED: null,
-               SELECT_TAB: null
-       }
+    featureGroupsEditor: {
+        OPEN: null,
+        CLOSE: null,
+        DATA_CHANGED: null,
+        SELECT_TAB: null
+    }
 });
 
 export const FG_EDITOR_FORM = 'FG_EDITOR_FORM';
 
 export const state = keyMirror({
-       SELECTED_FEATURE_GROUP_TAB: {
-               GENERAL: 1,
-               ENTITLEMENT_POOLS: 2,
-               LICENSE_KEY_GROUPS: 3
-       }
+    SELECTED_FEATURE_GROUP_TAB: {
+        GENERAL: 1,
+        ENTITLEMENT_POOLS: 2,
+        LICENSE_KEY_GROUPS: 3
+    }
 });
index 5688fc0..aa1081e 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes, FG_EDITOR_FORM, state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js';
-
-
+import {
+    actionTypes,
+    FG_EDITOR_FORM,
+    state as FeatureGroupStateConstants
+} from './FeatureGroupsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.featureGroupsEditor.OPEN:
-                       return {
-                               ...state,
-                               data: action.featureGroup || {},
-                               formReady: null,
-                               formName: FG_EDITOR_FORM,
-                               genericFieldInfo: {
-                                       'description': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}],
-                                               tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
-                                       },
-                                       'partNumber': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}],
-                                               tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
-                                       },
-                                       'manufacturerReferenceNumber': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 100}],
-                                               tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
-                                       },
-                                       'name': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}],
-                                               tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
-                                       }
-                               }
-                       };
-               case actionTypes.featureGroupsEditor.CLOSE:
-                       return {};
-               case actionTypes.featureGroupsEditor.SELECT_TAB:
-                       return {
-                               ...state,
-                               selectedTab: action.tab
-                       };
-
-               case actionTypes.featureGroupsEditor.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB:
-                       return {
-                               ...state,
-                               selectedEntitlementPoolsButtonTab: action.buttonTab
-                       };
-               case actionTypes.featureGroupsEditor.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB:
-                       return {
-                               ...state,
-                               selectedLicenseKeyGroupsButtonTab: action.buttonTab
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.featureGroupsEditor.OPEN:
+            return {
+                ...state,
+                data: action.featureGroup || {},
+                formReady: null,
+                formName: FG_EDITOR_FORM,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }],
+                        tabId:
+                            FeatureGroupStateConstants
+                                .SELECTED_FEATURE_GROUP_TAB.GENERAL
+                    },
+                    partNumber: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }],
+                        tabId:
+                            FeatureGroupStateConstants
+                                .SELECTED_FEATURE_GROUP_TAB.GENERAL
+                    },
+                    manufacturerReferenceNumber: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 100 }
+                        ],
+                        tabId:
+                            FeatureGroupStateConstants
+                                .SELECTED_FEATURE_GROUP_TAB.GENERAL
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ],
+                        tabId:
+                            FeatureGroupStateConstants
+                                .SELECTED_FEATURE_GROUP_TAB.GENERAL
+                    }
+                }
+            };
+        case actionTypes.featureGroupsEditor.CLOSE:
+            return {};
+        case actionTypes.featureGroupsEditor.SELECT_TAB:
+            return {
+                ...state,
+                selectedTab: action.tab
+            };
 
+        case actionTypes.featureGroupsEditor
+            .SELECTED_ENTITLEMENT_POOLS_BUTTONTAB:
+            return {
+                ...state,
+                selectedEntitlementPoolsButtonTab: action.buttonTab
+            };
+        case actionTypes.featureGroupsEditor
+            .SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB:
+            return {
+                ...state,
+                selectedLicenseKeyGroupsButtonTab: action.buttonTab
+            };
+        default:
+            return state;
+    }
 };
index 3b5f1c5..072bba4 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './FeatureGroupsConstants.js';
+import { actionTypes } from './FeatureGroupsConstants.js';
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FEATURE_GROUPS_LIST_LOADED:
-                       return [...action.response.results];
-               case actionTypes.ADD_FEATURE_GROUPS:
-                       return [...state, action.featureGroup];
-               case actionTypes.EDIT_FEATURE_GROUPS:
-                       const indexForEdit = state.findIndex(featureGroup => featureGroup.id === action.featureGroup.id);
-                       return [...state.slice(0, indexForEdit), action.featureGroup, ...state.slice(indexForEdit + 1)];
-               case actionTypes.DELETE_FEATURE_GROUPS:
-                       return state.filter(featureGroup => featureGroup.id !== action.featureGroupId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FEATURE_GROUPS_LIST_LOADED:
+            return [...action.response.results];
+        case actionTypes.ADD_FEATURE_GROUPS:
+            return [...state, action.featureGroup];
+        case actionTypes.EDIT_FEATURE_GROUPS:
+            const indexForEdit = state.findIndex(
+                featureGroup => featureGroup.id === action.featureGroup.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.featureGroup,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.DELETE_FEATURE_GROUPS:
+            return state.filter(
+                featureGroup => featureGroup.id !== action.featureGroupId
+            );
+        default:
+            return state;
+    }
 };
index b1b4ee8..e07777f 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants.js';
+import { actionTypes as licenseAgreementActionTypes } from './LicenseAgreementConstants.js';
 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 function baseUrl(licenseModelId, version) {
-       const restPrefix = Configuration.get('restPrefix');
-       const {id: versionId} = version;
-       return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-agreements`;
+    const restPrefix = Configuration.get('restPrefix');
+    const { id: versionId } = version;
+    return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-agreements`;
 }
 
 function fetchLicenseAgreementList(licenseModelId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
 }
 
 function fetchLicenseAgreement(licenseModelId, licenseAgreementId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${licenseAgreementId}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl(licenseModelId, version)}/${licenseAgreementId}`
+    );
 }
 
 function postLicenseAgreement(licenseModelId, licenseAgreement, version) {
-       return RestAPIUtil.post(baseUrl(licenseModelId, version), {
-               name: licenseAgreement.name,
-               description: licenseAgreement.description,
-               licenseTerm: licenseAgreement.licenseTerm,
-               requirementsAndConstrains: licenseAgreement.requirementsAndConstrains,
-               addedFeatureGroupsIds: licenseAgreement.featureGroupsIds
-       });
+    return RestAPIUtil.post(baseUrl(licenseModelId, version), {
+        name: licenseAgreement.name,
+        description: licenseAgreement.description,
+        licenseTerm: licenseAgreement.licenseTerm,
+        requirementsAndConstrains: licenseAgreement.requirementsAndConstrains,
+        addedFeatureGroupsIds: licenseAgreement.featureGroupsIds
+    });
 }
 
-function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version) {
-       const {featureGroupsIds = []} = licenseAgreement;
-       const {featureGroupsIds: prevFeatureGroupsIds = []} = previousLicenseAgreement;
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseAgreement.id}`, {
-               name: licenseAgreement.name,
-               description: licenseAgreement.description,
-               licenseTerm: licenseAgreement.licenseTerm,
-               requirementsAndConstrains: licenseAgreement.requirementsAndConstrains,
-               addedFeatureGroupsIds: featureGroupsIds.filter(featureGroupId => prevFeatureGroupsIds.indexOf(featureGroupId) === -1),
-               removedFeatureGroupsIds: prevFeatureGroupsIds.filter(prevFeatureGroupsId => featureGroupsIds.indexOf(prevFeatureGroupsId) === -1)
-       });
+function putLicenseAgreement(
+    licenseModelId,
+    previousLicenseAgreement,
+    licenseAgreement,
+    version
+) {
+    const { featureGroupsIds = [] } = licenseAgreement;
+    const {
+        featureGroupsIds: prevFeatureGroupsIds = []
+    } = previousLicenseAgreement;
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${licenseAgreement.id}`,
+        {
+            name: licenseAgreement.name,
+            description: licenseAgreement.description,
+            licenseTerm: licenseAgreement.licenseTerm,
+            requirementsAndConstrains:
+                licenseAgreement.requirementsAndConstrains,
+            addedFeatureGroupsIds: featureGroupsIds.filter(
+                featureGroupId =>
+                    prevFeatureGroupsIds.indexOf(featureGroupId) === -1
+            ),
+            removedFeatureGroupsIds: prevFeatureGroupsIds.filter(
+                prevFeatureGroupsId =>
+                    featureGroupsIds.indexOf(prevFeatureGroupsId) === -1
+            )
+        }
+    );
 }
 
 function deleteLicenseAgreement(licenseModelId, licenseAgreementId, version) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseAgreementId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(licenseModelId, version)}/${licenseAgreementId}`
+    );
 }
 
 export default {
+    fetchLicenseAgreementList(dispatch, { licenseModelId, version }) {
+        return fetchLicenseAgreementList(licenseModelId, version).then(
+            response =>
+                dispatch({
+                    type:
+                        licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
+                    response
+                })
+        );
+    },
 
-       fetchLicenseAgreementList(dispatch, {licenseModelId, version}) {
-               return fetchLicenseAgreementList(licenseModelId, version).then(response => dispatch({
-                       type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
-                       response
-               }));
-       },
+    fetchLicenseAgreement(
+        dispatch,
+        { licenseModelId, licenseAgreementId, version }
+    ) {
+        return fetchLicenseAgreement(
+            licenseModelId,
+            licenseAgreementId,
+            version
+        );
+    },
 
-       fetchLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId, version}) {
-               return fetchLicenseAgreement(licenseModelId, licenseAgreementId, version);
-       },
+    openLicenseAgreementEditor(
+        dispatch,
+        { licenseModelId, licenseAgreement, version }
+    ) {
+        FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+            licenseModelId,
+            version
+        });
+        dispatch({
+            type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN,
+            licenseAgreement
+        });
+    },
 
-       openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}) {
-               FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
-               dispatch({
-                       type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN,
-                       licenseAgreement
-               });
-       },
+    closeLicenseAgreementEditor(dispatch) {
+        dispatch({
+            type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE
+        });
+    },
 
-       closeLicenseAgreementEditor(dispatch) {
-               dispatch({
-                       type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE
-               });
-       },
+    saveLicenseAgreement(
+        dispatch,
+        { licenseModelId, previousLicenseAgreement, licenseAgreement, version }
+    ) {
+        if (previousLicenseAgreement) {
+            return putLicenseAgreement(
+                licenseModelId,
+                previousLicenseAgreement,
+                licenseAgreement,
+                version
+            ).then(() => {
+                this.fetchLicenseAgreementList(dispatch, {
+                    licenseModelId,
+                    version
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        } else {
+            return postLicenseAgreement(
+                licenseModelId,
+                licenseAgreement,
+                version
+            ).then(() => {
+                this.fetchLicenseAgreementList(dispatch, {
+                    licenseModelId,
+                    version
+                });
+                FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+                    licenseModelId,
+                    version
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        }
+    },
 
+    deleteLicenseAgreement(
+        dispatch,
+        { licenseModelId, licenseAgreementId, version }
+    ) {
+        return deleteLicenseAgreement(
+            licenseModelId,
+            licenseAgreementId,
+            version
+        ).then(() => {
+            dispatch({
+                type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT,
+                licenseAgreementId
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    },
 
-       saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version}) {
-               if (previousLicenseAgreement) {
-                       return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version).then(() => {
-                               this.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-               else {
-                       return postLicenseAgreement(licenseModelId, licenseAgreement, version).then(() => {
-                               this.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
-                               FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-       },
-
-       deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId, version}) {
-               return deleteLicenseAgreement(licenseModelId, licenseAgreementId, version).then(() => {
-                       dispatch({
-                               type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT,
-                               licenseAgreementId
-                       });
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
-
-       selectLicenseAgreementEditorTab(dispatch, {tab}) {
-               dispatch({
-                       type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_TAB,
-                       tab
-               });
-       }
+    selectLicenseAgreementEditorTab(dispatch, { tab }) {
+        dispatch({
+            type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_TAB,
+            tab
+        });
+    }
 };
index 181171d..65a4534 100644 (file)
  */
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import InputOptions, {
+    other as optionInputOther
+} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export const actionTypes = keyMirror({
-       LICENSE_AGREEMENT_LIST_LOADED: null,
-       DELETE_LICENSE_AGREEMENT: null,
-
-       licenseAgreementEditor: {
-               OPEN: null,
-               CLOSE: null,
-               DATA_CHANGED: null,
-               SELECT_TAB: null
-       }
+    LICENSE_AGREEMENT_LIST_LOADED: null,
+    DELETE_LICENSE_AGREEMENT: null,
 
+    licenseAgreementEditor: {
+        OPEN: null,
+        CLOSE: null,
+        DATA_CHANGED: null,
+        SELECT_TAB: null
+    }
 });
 
 export const LA_EDITOR_FORM = 'LA_EDITOR_FORM';
 
 export const enums = keyMirror({
-       SELECTED_LICENSE_AGREEMENT_TAB: {
-               GENERAL: 1,
-               FEATURE_GROUPS: 2
-       }
+    SELECTED_LICENSE_AGREEMENT_TAB: {
+        GENERAL: 1,
+        FEATURE_GROUPS: 2
+    }
 });
 
 export const defaultState = {
-       LICENSE_AGREEMENT_EDITOR_DATA: {
-               licenseTerm: {choice: '', other: ''}
-       }
+    LICENSE_AGREEMENT_EDITOR_DATA: {
+        licenseTerm: { choice: '', other: '' }
+    }
 };
 
 export const optionsInputValues = {
-       LICENSE_MODEL_TYPE: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Fixed_Term', title: 'Fixed Term'},
-               {enum: 'Perpetual', title: 'Perpetual'},
-               {enum: 'Unlimited', title: 'Unlimited'}
-       ]
+    LICENSE_MODEL_TYPE: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Fixed_Term', title: 'Fixed Term' },
+        { enum: 'Perpetual', title: 'Perpetual' },
+        { enum: 'Unlimited', title: 'Unlimited' }
+    ]
 };
 
-export const extractValue = (item) => {
-       if (item === undefined) {
-               return '';
-       } //TODO fix it later
+export const extractValue = item => {
+    if (item === undefined) {
+        return '';
+    } //TODO fix it later
 
-       return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+    return item
+        ? item.choice === optionInputOther.OTHER
+          ? item.other
+          : InputOptions.getTitleByName(optionsInputValues, item.choice)
+        : '';
 };
index 7d70da6..735531a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
 import LicenseAgreementEditorView from './LicenseAgreementEditorView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}) => {
+export const mapStateToProps = ({
+    licenseModel: { licenseAgreement, featureGroup }
+}) => {
+    let {
+        data,
+        selectedTab,
+        genericFieldInfo,
+        formReady
+    } = licenseAgreement.licenseAgreementEditor;
+    const list = licenseAgreement.licenseAgreementList;
+    const LANames = {};
 
+    let previousData;
+    const licenseAgreementId = data ? data.id : null;
+    if (licenseAgreementId) {
+        previousData = licenseAgreement.licenseAgreementList.find(
+            licenseAgreement => licenseAgreement.id === licenseAgreementId
+        );
+    }
 
-       let {data, selectedTab, genericFieldInfo, formReady} = licenseAgreement.licenseAgreementEditor;
-       const list = licenseAgreement.licenseAgreementList;
-       const LANames = {};
+    for (let i = 0; i < list.length; i++) {
+        LANames[list[i].name.toLowerCase()] = list[i].id;
+    }
 
-       let previousData;
-       const licenseAgreementId = data ? data.id : null;
-       if(licenseAgreementId) {
-               previousData = licenseAgreement.licenseAgreementList.find(licenseAgreement => licenseAgreement.id === licenseAgreementId);
-       }
+    const { featureGroupsList = [] } = featureGroup;
 
-       for (let i = 0; i < list.length; i++) {
-               LANames[list[i].name.toLowerCase()] = list[i].id;
-       }
+    let isFormValid = true;
+    let invalidTabs = [];
+    for (let field in genericFieldInfo) {
+        if (!genericFieldInfo[field].isValid) {
+            isFormValid = false;
+            let tabId = genericFieldInfo[field].tabId;
+            if (invalidTabs.indexOf(tabId) === -1) {
+                invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
+            }
+        }
+    }
 
-       const {featureGroupsList = []} = featureGroup;
-
-       let isFormValid = true;
-       let invalidTabs = [];
-       for (let field in genericFieldInfo) {
-               if (!genericFieldInfo[field].isValid) {
-                       isFormValid = false;
-                       let tabId = genericFieldInfo[field].tabId;
-                       if (invalidTabs.indexOf(tabId) === -1) {
-                               invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
-                       }
-               }
-       }
-
-       return {
-               data,
-               previousData,
-               selectedTab,
-               featureGroupsList,
-               LANames,
-               genericFieldInfo,
-               isFormValid,
-               formReady,
-               invalidTabs
-       };
+    return {
+        data,
+        previousData,
+        selectedTab,
+        featureGroupsList,
+        LANames,
+        genericFieldInfo,
+        isFormValid,
+        formReady,
+        invalidTabs
+    };
 };
 
-export const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onTabSelect: tab => LicenseAgreementActionHelper.selectLicenseAgreementEditorTab(dispatch, {tab}),
-               onCancel: () => LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch),
-               onSubmit: ({previousLicenseAgreement, licenseAgreement}) => {
-                       LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch);
-                       LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version});
-               },
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
+export const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onTabSelect: tab =>
+            LicenseAgreementActionHelper.selectLicenseAgreementEditorTab(
+                dispatch,
+                {
+                    tab
+                }
+            ),
+        onCancel: () =>
+            LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch),
+        onSubmit: ({ previousLicenseAgreement, licenseAgreement }) => {
+            LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch);
+            LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {
+                licenseModelId,
+                previousLicenseAgreement,
+                licenseAgreement,
+                version
+            });
+        },
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseAgreementEditorView
+);
index 9cff279..0d3fb2a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, defaultState, LA_EDITOR_FORM, enums as LicenseAgreementEnums} from './LicenseAgreementConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import {
+    actionTypes,
+    defaultState,
+    LA_EDITOR_FORM,
+    enums as LicenseAgreementEnums
+} from './LicenseAgreementConstants.js';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.licenseAgreementEditor.OPEN:
-                       return {
-                               ...state,
-                               formReady: null,
-                               formName: LA_EDITOR_FORM,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}],
-                                               tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
-                                       },
-                                       'requirementsAndConstrains' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}],
-                                               tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
-                                       },
-                                       'licenseTerm' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}],
-                                               tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}],
-                                               tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
-                                       }
-                               },
-                               data: action.licenseAgreement ? { ...action.licenseAgreement } : defaultState.LICENSE_AGREEMENT_EDITOR_DATA
-                       };
-               case actionTypes.licenseAgreementEditor.CLOSE:
-                       return {};
-               case actionTypes.licenseAgreementEditor.SELECT_TAB:
-                       return {
-                               ...state,
-                               selectedTab: action.tab
-                       };
-               default:
-                       return state;
-       }
-
+    switch (action.type) {
+        case actionTypes.licenseAgreementEditor.OPEN:
+            return {
+                ...state,
+                formReady: null,
+                formName: LA_EDITOR_FORM,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }],
+                        tabId:
+                            LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB
+                                .GENERAL
+                    },
+                    requirementsAndConstrains: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }],
+                        tabId:
+                            LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB
+                                .GENERAL
+                    },
+                    licenseTerm: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            {
+                                type: 'requiredChoiceWithOther',
+                                data: optionInputOther.OTHER
+                            }
+                        ],
+                        tabId:
+                            LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB
+                                .GENERAL
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 25 }
+                        ],
+                        tabId:
+                            LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB
+                                .GENERAL
+                    }
+                },
+                data: action.licenseAgreement
+                    ? { ...action.licenseAgreement }
+                    : defaultState.LICENSE_AGREEMENT_EDITOR_DATA
+            };
+        case actionTypes.licenseAgreementEditor.CLOSE:
+            return {};
+        case actionTypes.licenseAgreementEditor.SELECT_TAB:
+            return {
+                ...state,
+                selectedTab: action.tab
+            };
+        default:
+            return state;
+    }
 };
index a3e73f4..cc16dd9 100644 (file)
@@ -17,7 +17,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {TabsForm as Form} from 'nfvo-components/input/validation/Form.jsx';
+import { TabsForm as Form } from 'nfvo-components/input/validation/Form.jsx';
 import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
 import Tab from 'sdc-ui/lib/react/Tab.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
@@ -25,176 +25,278 @@ import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Validator from 'nfvo-utils/Validator.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
-import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues, LA_EDITOR_FORM} from './LicenseAgreementConstants.js';
+import {
+    enums as LicenseAgreementEnums,
+    optionsInputValues as LicenseAgreementOptionsInputValues,
+    LA_EDITOR_FORM
+} from './LicenseAgreementConstants.js';
 
 const dualBoxFilterTitle = {
-       left: i18n('Available Feature Groups'),
-       right: i18n('Selected Feature Groups')
+    left: i18n('Available Feature Groups'),
+    right: i18n('Selected Feature Groups')
 };
 
 const LicenseAgreementPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       requirementsAndConstrains: PropTypes.string,
-       licenseTerm: PropTypes.object,
-       featureGroupsIds: PropTypes.arrayOf(PropTypes.string),
-       version: PropTypes.object
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    requirementsAndConstrains: PropTypes.string,
+    licenseTerm: PropTypes.object,
+    featureGroupsIds: PropTypes.arrayOf(PropTypes.string),
+    version: PropTypes.object
 });
 
-
-const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName}) => {
-       let {name, description, requirementsAndConstrains, licenseTerm} = data;
-       return (
-               <GridSection hasLastColSet>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       isValid={genericFieldInfo.name.isValid}
-                                       errorText={genericFieldInfo.name.errorText}
-                                       onChange={name => onDataChanged({name}, LA_EDITOR_FORM, { name: validateName })}
-                                       label={i18n('Name')}
-                                       value={name}
-                                       data-test-id='create-la-name'
-                                       name='license-agreement-name'
-                                       isRequired={true}
-                                       type='text'/>
-                               <Input
-                                       isValid={genericFieldInfo.requirementsAndConstrains.isValid}
-                                       errorText={genericFieldInfo.requirementsAndConstrains.errorText}
-                                       onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains}, LA_EDITOR_FORM)}
-                                       label={i18n('Requirements and Constraints')}
-                                       value={requirementsAndConstrains}
-                                       data-test-id='create-la-requirements-constants'
-                                       name='license-agreement-requirements-and-constraints'
-                                       type='textarea'/>
-                               <InputOptions
-                                       onInputChange={()=>{}}
-                                       isMultiSelect={false}
-                                       onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}},
-                                               LA_EDITOR_FORM)}
-                                       onOtherChange={licenseTerm => onDataChanged({licenseTerm:{choice: optionInputOther.OTHER,
-                                               other: licenseTerm}}, LA_EDITOR_FORM)}
-                                       label={i18n('License Term')}
-                                       data-test-id='create-la-license-term'
-                                       isRequired={true}
-                                       type='select'
-                                       selectedEnum={licenseTerm && licenseTerm.choice}
-                                       otherValue={licenseTerm && licenseTerm.other}
-                                       values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}
-                                       isValid={genericFieldInfo.licenseTerm.isValid}
-                                       errorText={genericFieldInfo.licenseTerm.errorText} />
-                       </GridItem>
-                       <GridItem colSpan={2} stretch lastColInRow>
-                               <Input
-                                       isValid={genericFieldInfo.description.isValid}
-                                       errorText={genericFieldInfo.description.errorText}
-                                       onChange={description => onDataChanged({description}, LA_EDITOR_FORM)}
-                                       label={i18n('Description')}
-                                       value={description}
-                                       overlayPos='bottom'
-                                       data-test-id='create-la-description'
-                                       name='license-agreement-description'
-                                       type='textarea'/>
-                       </GridItem>
-               </GridSection>
-       );
+const GeneralTabContent = ({
+    data,
+    genericFieldInfo,
+    onDataChanged,
+    validateName
+}) => {
+    let { name, description, requirementsAndConstrains, licenseTerm } = data;
+    return (
+        <GridSection hasLastColSet>
+            <GridItem colSpan={2}>
+                <Input
+                    isValid={genericFieldInfo.name.isValid}
+                    errorText={genericFieldInfo.name.errorText}
+                    onChange={name =>
+                        onDataChanged({ name }, LA_EDITOR_FORM, {
+                            name: validateName
+                        })
+                    }
+                    label={i18n('Name')}
+                    value={name}
+                    data-test-id="create-la-name"
+                    name="license-agreement-name"
+                    isRequired={true}
+                    type="text"
+                />
+                <Input
+                    isValid={genericFieldInfo.requirementsAndConstrains.isValid}
+                    errorText={
+                        genericFieldInfo.requirementsAndConstrains.errorText
+                    }
+                    onChange={requirementsAndConstrains =>
+                        onDataChanged(
+                            { requirementsAndConstrains },
+                            LA_EDITOR_FORM
+                        )
+                    }
+                    label={i18n('Requirements and Constraints')}
+                    value={requirementsAndConstrains}
+                    data-test-id="create-la-requirements-constants"
+                    name="license-agreement-requirements-and-constraints"
+                    type="textarea"
+                />
+                <InputOptions
+                    onInputChange={() => {}}
+                    isMultiSelect={false}
+                    onEnumChange={licenseTerm =>
+                        onDataChanged(
+                            { licenseTerm: { choice: licenseTerm, other: '' } },
+                            LA_EDITOR_FORM
+                        )
+                    }
+                    onOtherChange={licenseTerm =>
+                        onDataChanged(
+                            {
+                                licenseTerm: {
+                                    choice: optionInputOther.OTHER,
+                                    other: licenseTerm
+                                }
+                            },
+                            LA_EDITOR_FORM
+                        )
+                    }
+                    label={i18n('License Term')}
+                    data-test-id="create-la-license-term"
+                    isRequired={true}
+                    type="select"
+                    selectedEnum={licenseTerm && licenseTerm.choice}
+                    otherValue={licenseTerm && licenseTerm.other}
+                    values={
+                        LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE
+                    }
+                    isValid={genericFieldInfo.licenseTerm.isValid}
+                    errorText={genericFieldInfo.licenseTerm.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2} stretch lastColInRow>
+                <Input
+                    isValid={genericFieldInfo.description.isValid}
+                    errorText={genericFieldInfo.description.errorText}
+                    onChange={description =>
+                        onDataChanged({ description }, LA_EDITOR_FORM)
+                    }
+                    label={i18n('Description')}
+                    value={description}
+                    overlayPos="bottom"
+                    data-test-id="create-la-description"
+                    name="license-agreement-description"
+                    type="textarea"
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 class LicenseAgreementEditorView extends React.Component {
+    static propTypes = {
+        data: LicenseAgreementPropType,
+        previousData: LicenseAgreementPropType,
+        LANames: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired,
 
-       static propTypes = {
-               data: LicenseAgreementPropType,
-               previousData: LicenseAgreementPropType,
-               LANames: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired,
-
-               selectedTab: PropTypes.number,
-               onTabSelect: PropTypes.func,
+        selectedTab: PropTypes.number,
+        onTabSelect: PropTypes.func,
 
-               selectedFeatureGroupsButtonTab: PropTypes.number,
-               onFeatureGroupsButtonTabSelect: PropTypes.func,
-               featureGroupsList: DualListboxView.propTypes.availableList
-       };
+        selectedFeatureGroupsButtonTab: PropTypes.number,
+        onFeatureGroupsButtonTabSelect: PropTypes.func,
+        featureGroupsList: DualListboxView.propTypes.availableList
+    };
 
-       static defaultProps = {
-               selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL,
-               data: {}
-       };
+    static defaultProps = {
+        selectedTab:
+            LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL,
+        data: {}
+    };
 
-       state = {
-               localFeatureGroupsListFilter: ''
-       };
+    state = {
+        localFeatureGroupsListFilter: ''
+    };
 
-       render() {
-               let {selectedTab, onTabSelect, isReadOnlyMode, featureGroupsList, data, onDataChanged, genericFieldInfo} = this.props;
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       ref='validationForm'
-                                       hasButtons={true}
-                                       onSubmit={ () => this.submit() }
-                                       onReset={ () => this.props.onCancel() }
-                                       labledButtons={true}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       isValid={this.props.isFormValid}
-                                       formReady={this.props.formReady}
-                                       onValidateForm={() => this.props.onValidateForm(LA_EDITOR_FORM) }
-                                       className='license-model-form license-agreement-form'>
-                                       <Tabs activeTab={onTabSelect ? selectedTab : undefined} onTabClick={onTabSelect} invalidTabs={this.props.invalidTabs} >
-                                               <Tab
-                                                       tabId={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
-                                                       data-test-id='general-tab'
-                                                       title={i18n('General')}>
-                                                               <fieldset disabled={isReadOnlyMode}>
-                                                                       <GeneralTabContent data={data} genericFieldInfo={genericFieldInfo} onDataChanged={onDataChanged} validateLTChoice={(value)=>this.validateLTChoice(value)}
-                                                                                  validateName={(value)=>this.validateName(value)}/>
-                                                               </fieldset>
-                                               </Tab>
-                                               <Tab
-                                                       tabId={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
-                                                       data-test-id='feature-group-tab'
-                                                       title={i18n('Feature Groups')}>
-                                                               <fieldset disabled={isReadOnlyMode}>
-                                                       {featureGroupsList.length > 0 ?
-                                                                       <DualListboxView
-                                                                               isReadOnlyMode={isReadOnlyMode}
-                                                                               filterTitle={dualBoxFilterTitle}
-                                                                               selectedValuesList={data.featureGroupsIds}
-                                                                               availableList={featureGroupsList}
-                                                                               onChange={ selectedValuesList => onDataChanged( { featureGroupsIds: selectedValuesList }, LA_EDITOR_FORM )}/> :
-                                                                       <p>{i18n('There are no available feature groups')}</p>}
-                                                               </fieldset>
-                                               </Tab>
-                                       </Tabs>
-                               </Form>}
-                       </div>
-               );
-       }
+    render() {
+        let {
+            selectedTab,
+            onTabSelect,
+            isReadOnlyMode,
+            featureGroupsList,
+            data,
+            onDataChanged,
+            genericFieldInfo
+        } = this.props;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => this.props.onCancel()}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() =>
+                            this.props.onValidateForm(LA_EDITOR_FORM)
+                        }
+                        className="license-model-form license-agreement-form">
+                        <Tabs
+                            activeTab={onTabSelect ? selectedTab : undefined}
+                            onTabClick={onTabSelect}
+                            invalidTabs={this.props.invalidTabs}>
+                            <Tab
+                                tabId={
+                                    LicenseAgreementEnums
+                                        .SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
+                                }
+                                data-test-id="general-tab"
+                                title={i18n('General')}>
+                                <fieldset disabled={isReadOnlyMode}>
+                                    <GeneralTabContent
+                                        data={data}
+                                        genericFieldInfo={genericFieldInfo}
+                                        onDataChanged={onDataChanged}
+                                        validateLTChoice={value =>
+                                            this.validateLTChoice(value)
+                                        }
+                                        validateName={value =>
+                                            this.validateName(value)
+                                        }
+                                    />
+                                </fieldset>
+                            </Tab>
+                            <Tab
+                                tabId={
+                                    LicenseAgreementEnums
+                                        .SELECTED_LICENSE_AGREEMENT_TAB
+                                        .FEATURE_GROUPS
+                                }
+                                data-test-id="feature-group-tab"
+                                title={i18n('Feature Groups')}>
+                                <fieldset disabled={isReadOnlyMode}>
+                                    {featureGroupsList.length > 0 ? (
+                                        <DualListboxView
+                                            isReadOnlyMode={isReadOnlyMode}
+                                            filterTitle={dualBoxFilterTitle}
+                                            selectedValuesList={
+                                                data.featureGroupsIds
+                                            }
+                                            availableList={featureGroupsList}
+                                            onChange={selectedValuesList =>
+                                                onDataChanged(
+                                                    {
+                                                        featureGroupsIds: selectedValuesList
+                                                    },
+                                                    LA_EDITOR_FORM
+                                                )
+                                            }
+                                        />
+                                    ) : (
+                                        <p>
+                                            {i18n(
+                                                'There are no available feature groups'
+                                            )}
+                                        </p>
+                                    )}
+                                </fieldset>
+                            </Tab>
+                        </Tabs>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       submit() {
-               const {data: licenseAgreement, previousData: previousLicenseAgreement} = this.props;
-               this.props.onSubmit({licenseAgreement, previousLicenseAgreement});
-       }
+    submit() {
+        const {
+            data: licenseAgreement,
+            previousData: previousLicenseAgreement
+        } = this.props;
+        this.props.onSubmit({ licenseAgreement, previousLicenseAgreement });
+    }
 
-       validateLTChoice(value) {
-               if (!value.choice) {
-                       return {isValid: false, errorText: i18n('Field is required')};
-               }
-               return {isValid: true, errorText: ''};
-       }
+    validateLTChoice(value) {
+        if (!value.choice) {
+            return { isValid: false, errorText: i18n('Field is required') };
+        }
+        return { isValid: true, errorText: '' };
+    }
 
-       validateName(value) {
-               const {data: {id}, LANames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LANames});
+    validateName(value) {
+        const { data: { id }, LANames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: LANames
+        });
 
-               return !isExists ?  {isValid: true, errorText: ''} :
-                       {isValid: false, errorText: i18n('License Agreement by the name \'' + value + '\' already exists. License agreement name must be unique')};
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "License Agreement by the name '" +
+                          value +
+                          "' already exists. License agreement name must be unique"
+                  )
+              };
+    }
 }
 
 export default LicenseAgreementEditorView;
index 72474ec..cba3973 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
 import LicenseAgreementListEditorView from './LicenseAgreementListEditorView.jsx';
-import {actionTypes as globalMoadlActions}  from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as globalMoadlActions } from 'nfvo-components/modal/GlobalModalConstants.js';
 
-const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) => {
-
-       let {licenseAgreementList} = licenseAgreement;
-       let {data} = licenseAgreement.licenseAgreementEditor;
-       let {vendorName, version} = licenseModelEditor.data;
-
-       return {
-               vendorName,
-               version,
-               licenseAgreementList,
-               isDisplayModal: Boolean(data),
-               isModalInEditMode: Boolean(data && data.id)
-       };
+const mapStateToProps = ({
+    licenseModel: { licenseAgreement, licenseModelEditor }
+}) => {
+    let { licenseAgreementList } = licenseAgreement;
+    let { data } = licenseAgreement.licenseAgreementEditor;
+    let { vendorName, version } = licenseModelEditor.data;
 
+    return {
+        vendorName,
+        version,
+        licenseAgreementList,
+        isDisplayModal: Boolean(data),
+        isModalInEditMode: Boolean(data && data.id)
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
-       return {
-               onAddLicenseAgreementClick: (version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version}),
-               onEditLicenseAgreementClick: (licenseAgreement, version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}),
-               onDeleteLicenseAgreement: (licenseAgreement, version) => dispatch({
-                       type: globalMoadlActions.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{name}"?', {name: licenseAgreement.name}),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=>LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreement.id, version})
-                       }
-               })
-       };
+const mapActionsToProps = (dispatch, { licenseModelId }) => {
+    return {
+        onAddLicenseAgreementClick: version =>
+            LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {
+                licenseModelId,
+                version
+            }),
+        onEditLicenseAgreementClick: (licenseAgreement, version) =>
+            LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {
+                licenseModelId,
+                licenseAgreement,
+                version
+            }),
+        onDeleteLicenseAgreement: (licenseAgreement, version) =>
+            dispatch({
+                type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{name}"?', {
+                        name: licenseAgreement.name
+                    }),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        LicenseAgreementActionHelper.deleteLicenseAgreement(
+                            dispatch,
+                            {
+                                licenseModelId,
+                                licenseAgreementId: licenseAgreement.id,
+                                version
+                            }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementListEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseAgreementListEditorView
+);
index ad3cdb0..acec1e0 100644 (file)
@@ -21,107 +21,151 @@ import Modal from 'nfvo-components/modal/Modal.jsx';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import LicenseAgreementEditor from './LicenseAgreementEditor.js';
-import {extractValue} from './LicenseAgreementConstants';
+import { extractValue } from './LicenseAgreementConstants';
 
 class LicenseAgreementListEditorView extends React.Component {
-       static propTypes = {
-               vendorName: PropTypes.string,
-               licenseModelId: PropTypes.string.isRequired,
-               licenseAgreementList: PropTypes.array,
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               isDisplayModal: PropTypes.bool,
-               isModalInEditMode: PropTypes.bool,
-               onAddLicenseAgreementClick: PropTypes.func,
-               onEditLicenseAgreementClick: PropTypes.func,
-               onDeleteLicenseAgreement: PropTypes.func,
-       };
+    static propTypes = {
+        vendorName: PropTypes.string,
+        licenseModelId: PropTypes.string.isRequired,
+        licenseAgreementList: PropTypes.array,
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        isDisplayModal: PropTypes.bool,
+        isModalInEditMode: PropTypes.bool,
+        onAddLicenseAgreementClick: PropTypes.func,
+        onEditLicenseAgreementClick: PropTypes.func,
+        onDeleteLicenseAgreement: PropTypes.func
+    };
 
-       static defaultProps = {
-               licenseAgreementList: []
-       };
+    static defaultProps = {
+        licenseAgreementList: []
+    };
 
-       state = {
-               localFilter: ''
-       };
+    state = {
+        localFilter: ''
+    };
 
-       render() {
-               const {licenseModelId, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
-               const {onAddLicenseAgreementClick} = this.props;
-               const {localFilter} = this.state;
+    render() {
+        const {
+            licenseModelId,
+            isReadOnlyMode,
+            isDisplayModal,
+            isModalInEditMode,
+            version
+        } = this.props;
+        const { onAddLicenseAgreementClick } = this.props;
+        const { localFilter } = this.state;
 
-               return (
-                       <div className='license-model-list-editor license-agreement-list-editor'>
-                               <ListEditorView
-                                       title={i18n('License Agreements')}
-                                       plusButtonTitle={i18n('Add License Agreement')}
-                                       onAdd={() => onAddLicenseAgreementClick(version)}
-                                       filterValue={localFilter}
-                                       onFilter={value => this.setState({localFilter: value})}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       {this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version))}
-                               </ListEditorView>
-                               <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-modal license-agreement-modal'>
-                                       <Modal.Header>
-                                               <Modal.Title>{`${isModalInEditMode ? i18n('Edit License Agreement') : i18n('Create New License Agreement')}`}</Modal.Title>
-                                       </Modal.Header>
-                                       <Modal.Body>
-                                               {
-                                                       isDisplayModal && (
-                                                               <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} />
-                                                       )
-                                               }
-                                       </Modal.Body>
-                               </Modal>
-                       </div>
-               );
-       }
+        return (
+            <div className="license-model-list-editor license-agreement-list-editor">
+                <ListEditorView
+                    title={i18n('License Agreements')}
+                    plusButtonTitle={i18n('Add License Agreement')}
+                    onAdd={() => onAddLicenseAgreementClick(version)}
+                    filterValue={localFilter}
+                    onFilter={value => this.setState({ localFilter: value })}
+                    isReadOnlyMode={isReadOnlyMode}>
+                    {this.filterList().map(licenseAgreement =>
+                        this.renderLicenseAgreementListItem(
+                            licenseAgreement,
+                            isReadOnlyMode,
+                            version
+                        )
+                    )}
+                </ListEditorView>
+                <Modal
+                    show={isDisplayModal}
+                    bsSize="large"
+                    animation={true}
+                    className="onborading-modal license-model-modal license-agreement-modal">
+                    <Modal.Header>
+                        <Modal.Title>{`${
+                            isModalInEditMode
+                                ? i18n('Edit License Agreement')
+                                : i18n('Create New License Agreement')
+                        }`}</Modal.Title>
+                    </Modal.Header>
+                    <Modal.Body>
+                        {isDisplayModal && (
+                            <LicenseAgreementEditor
+                                version={version}
+                                licenseModelId={licenseModelId}
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    </Modal.Body>
+                </Modal>
+            </div>
+        );
+    }
 
-       filterList() {
-               let {licenseAgreementList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return licenseAgreementList.filter(({name = '', description = '', licenseTerm = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter) || escape(extractValue(licenseTerm)).match(filter);
-                       });
-               }
-               else {
-                       return licenseAgreementList;
-               }
-       }
+    filterList() {
+        let { licenseAgreementList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return licenseAgreementList.filter(
+                ({ name = '', description = '', licenseTerm = '' }) => {
+                    return (
+                        escape(name).match(filter) ||
+                        escape(description).match(filter) ||
+                        escape(extractValue(licenseTerm)).match(filter)
+                    );
+                }
+            );
+        } else {
+            return licenseAgreementList;
+        }
+    }
 
-       renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version) {
-               let {id, name, description, licenseTerm, featureGroupsIds = []} = licenseAgreement;
-               let {onEditLicenseAgreementClick, onDeleteLicenseAgreement} = this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               onSelect={() => onEditLicenseAgreementClick(licenseAgreement, version)}
-                               onDelete={() => onDeleteLicenseAgreement(licenseAgreement, version)}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div className='text name'>{name}</div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='list-editor-item-view-field-tight'>
-                                               <div className='title'>{i18n('Type')}</div>
-                                               <div className='text type'>{extractValue(licenseTerm)}</div>
-                                       </div>
-                                       <div className='list-editor-item-view-field-tight'>
-                                               <div className='title'>{i18n('Feature')}</div>
-                                               <div className='title'>{i18n('Groups')}</div>
-                                               <div className='feature-groups-count'>{featureGroupsIds.length}</div>
-                                       </div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Description')}</div>
-                                       <div className='text description'>{description}</div>
-                               </div>
-                       </ListEditorItemView>
-               );
-       }
+    renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version) {
+        let {
+            id,
+            name,
+            description,
+            licenseTerm,
+            featureGroupsIds = []
+        } = licenseAgreement;
+        let {
+            onEditLicenseAgreementClick,
+            onDeleteLicenseAgreement
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                onSelect={() =>
+                    onEditLicenseAgreementClick(licenseAgreement, version)
+                }
+                onDelete={() =>
+                    onDeleteLicenseAgreement(licenseAgreement, version)
+                }
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div className="text name">{name}</div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="list-editor-item-view-field-tight">
+                        <div className="title">{i18n('Type')}</div>
+                        <div className="text type">
+                            {extractValue(licenseTerm)}
+                        </div>
+                    </div>
+                    <div className="list-editor-item-view-field-tight">
+                        <div className="title">{i18n('Feature')}</div>
+                        <div className="title">{i18n('Groups')}</div>
+                        <div className="feature-groups-count">
+                            {featureGroupsIds.length}
+                        </div>
+                    </div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Description')}</div>
+                    <div className="text description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
 }
 
 export default LicenseAgreementListEditorView;
index 7d1a5ef..213a63d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants';
+import { actionTypes as licenseAgreementActionTypes } from './LicenseAgreementConstants';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED:
-                       return [...action.response.results];
-               case licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT:
-                       return state.filter(licenseAgreement => licenseAgreement.id !== action.licenseAgreementId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED:
+            return [...action.response.results];
+        case licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT:
+            return state.filter(
+                licenseAgreement =>
+                    licenseAgreement.id !== action.licenseAgreementId
+            );
+        default:
+            return state;
+    }
 };
index 674c329..ebbe84a 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes as licenseKeyGroupsConstants} from './LicenseKeyGroupsConstants.js';
-import {actionTypes as limitEditorActions} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
-import {default as getValue, getStrValue} from 'nfvo-utils/getValue.js';
+import { actionTypes as licenseKeyGroupsConstants } from './LicenseKeyGroupsConstants.js';
+import { actionTypes as limitEditorActions } from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import { default as getValue, getStrValue } from 'nfvo-utils/getValue.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 function baseUrl(licenseModelId, version) {
-       const restPrefix = Configuration.get('restPrefix');
-       const {id: versionId} = version;
-       return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-key-groups`;
+    const restPrefix = Configuration.get('restPrefix');
+    const { id: versionId } = version;
+    return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-key-groups`;
 }
 
 function fetchLicenseKeyGroupsList(licenseModelId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
 }
 
 function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}`
+    );
 }
 
 function postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
-       return RestAPIUtil.post(baseUrl(licenseModelId, version), {
-               name: licenseKeyGroup.name,
-               description: licenseKeyGroup.description,
-               operationalScope: getValue(licenseKeyGroup.operationalScope),
-               type: licenseKeyGroup.type,
-               increments: licenseKeyGroup.increments,
-               thresholdValue: licenseKeyGroup.thresholdValue,
-               thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
-               startDate: licenseKeyGroup.startDate,
-               expiryDate: licenseKeyGroup.expiryDate
-       });
+    return RestAPIUtil.post(baseUrl(licenseModelId, version), {
+        name: licenseKeyGroup.name,
+        description: licenseKeyGroup.description,
+        operationalScope: getValue(licenseKeyGroup.operationalScope),
+        type: licenseKeyGroup.type,
+        increments: licenseKeyGroup.increments,
+        thresholdValue: licenseKeyGroup.thresholdValue,
+        thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
+        startDate: licenseKeyGroup.startDate,
+        expiryDate: licenseKeyGroup.expiryDate
+    });
 }
 
 function putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroup.id}`, {
-               name: licenseKeyGroup.name,
-               description: licenseKeyGroup.description,
-               operationalScope: getValue(licenseKeyGroup.operationalScope),
-               type: licenseKeyGroup.type,
-               increments: licenseKeyGroup.increments,
-               thresholdValue: licenseKeyGroup.thresholdValue,
-               thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
-               startDate: licenseKeyGroup.startDate,
-               expiryDate: licenseKeyGroup.expiryDate
-       });
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${licenseKeyGroup.id}`,
+        {
+            name: licenseKeyGroup.name,
+            description: licenseKeyGroup.description,
+            operationalScope: getValue(licenseKeyGroup.operationalScope),
+            type: licenseKeyGroup.type,
+            increments: licenseKeyGroup.increments,
+            thresholdValue: licenseKeyGroup.thresholdValue,
+            thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
+            startDate: licenseKeyGroup.startDate,
+            expiryDate: licenseKeyGroup.expiryDate
+        }
+    );
 }
 
 function fetchLimitsList(licenseModelId, licenseKeyGroupId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`);
+    return RestAPIUtil.fetch(
+        `${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`
+    );
 }
 
 function deleteLimit(licenseModelId, licenseKeyGroupId, version, limitId) {
-       return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits/${limitId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(
+            licenseModelId,
+            version
+        )}/${licenseKeyGroupId}/limits/${limitId}`
+    );
 }
 
 function postLimit(licenseModelId, licenseKeyGroupId, version, limit) {
-       return RestAPIUtil.post(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`, {
-               name: limit.name,
-               type: limit.type,
-               description: limit.description,
-               metric: getStrValue(limit.metric),
-               value: limit.value,
-               unit: getStrValue(limit.unit),
-               aggregationFunction: getValue(limit.aggregationFunction),
-               time: getValue(limit.time)
-       });
+    return RestAPIUtil.post(
+        `${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`,
+        {
+            name: limit.name,
+            type: limit.type,
+            description: limit.description,
+            metric: getStrValue(limit.metric),
+            value: limit.value,
+            unit: getStrValue(limit.unit),
+            aggregationFunction: getValue(limit.aggregationFunction),
+            time: getValue(limit.time)
+        }
+    );
 }
 
 function putLimit(licenseModelId, licenseKeyGroupId, version, limit) {
-
-       return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits/${limit.id}`, {
-               name: limit.name,
-               type: limit.type,
-               description: limit.description,
-               metric: getStrValue(limit.metric),
-               value: limit.value,
-               unit: getStrValue(limit.unit),
-               aggregationFunction: getValue(limit.aggregationFunction),
-               time: getValue(limit.time)
-       });
+    return RestAPIUtil.put(
+        `${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits/${
+            limit.id
+        }`,
+        {
+            name: limit.name,
+            type: limit.type,
+            description: limit.description,
+            metric: getStrValue(limit.metric),
+            value: limit.value,
+            unit: getStrValue(limit.unit),
+            aggregationFunction: getValue(limit.aggregationFunction),
+            time: getValue(limit.time)
+        }
+    );
 }
 
 export default {
-       fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}) {
-               return fetchLicenseKeyGroupsList(licenseModelId, version).then(response => dispatch({
-                       type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_LIST_LOADED,
-                       response
-               }));
-       },
-
-       openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup, licenseModelId, version} = {}) {
-               if (licenseModelId && version) {
-                       this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
-               }
-               dispatch({
-                       type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.OPEN,
-                       licenseKeyGroup
-               });
-       },
-
-       closeLicenseKeyGroupEditor(dispatch){
-               dispatch({
-                       type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.CLOSE
-               });
-       },
-
-       saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version}) {
-               if (previousLicenseKeyGroup) {
-                       return putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(() => {
-                               dispatch({
-                                       type: licenseKeyGroupsConstants.EDIT_LICENSE_KEY_GROUP,
-                                       licenseKeyGroup
-                               });
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-               else {
-                       return postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(response => {
-                               dispatch({
-                                       type: licenseKeyGroupsConstants.ADD_LICENSE_KEY_GROUP,
-                                       licenseKeyGroup: {
-                                               ...licenseKeyGroup,
-                                               referencingFeatureGroups: [],
-                                               id: response.value
-                                       }
-                               });
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-                       });
-               }
-
-
-       },
-
-       deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId, version}){
-               return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version).then(()=> {
-                       dispatch({
-                               type: licenseKeyGroupsConstants.DELETE_LICENSE_KEY_GROUP,
-                               licenseKeyGroupId
-                       });
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
-
-       hideDeleteConfirm(dispatch) {
-               dispatch({
-                       type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
-                       licenseKeyGroupToDelete: false
-               });
-       },
-
-       openDeleteLicenseAgreementConfirm(dispatch, {licenseKeyGroup}) {
-               dispatch({
-                       type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
-                       licenseKeyGroupToDelete: licenseKeyGroup
-               });
-       },
-
-
-       fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup}) {
-               return fetchLimitsList(licenseModelId, licenseKeyGroup.id, version).then(response => {
-                       dispatch({
-                               type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.LIMITS_LIST_LOADED,
-                               response
-                       });
-               });
-       },
-
-       submitLimit(dispatch, {licenseModelId, version, licenseKeyGroup, limit}) {
-               const promise = limit.id ? putLimit(licenseModelId,licenseKeyGroup.id, version, limit) :
-                        postLimit(licenseModelId,licenseKeyGroup.id, version, limit);
-               return promise.then(() => {
-                       dispatch({
-                               type: limitEditorActions.CLOSE
-                       });
-                       this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       },
-
-       deleteLimit(dispatch, {licenseModelId, version, licenseKeyGroup, limit}) {
-               return deleteLimit(licenseModelId,licenseKeyGroup.id, version, limit.id).then(() => {
-                       this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
-                       return ItemsHelper.checkItemStatus(dispatch, {itemId: licenseModelId, versionId: version.id});
-               });
-       }
+    fetchLicenseKeyGroupsList(dispatch, { licenseModelId, version }) {
+        return fetchLicenseKeyGroupsList(licenseModelId, version).then(
+            response =>
+                dispatch({
+                    type:
+                        licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_LIST_LOADED,
+                    response
+                })
+        );
+    },
+
+    openLicenseKeyGroupsEditor(
+        dispatch,
+        { licenseKeyGroup, licenseModelId, version } = {}
+    ) {
+        if (licenseModelId && version) {
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                licenseKeyGroup
+            });
+        }
+        dispatch({
+            type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.OPEN,
+            licenseKeyGroup
+        });
+    },
+
+    closeLicenseKeyGroupEditor(dispatch) {
+        dispatch({
+            type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.CLOSE
+        });
+    },
+
+    saveLicenseKeyGroup(
+        dispatch,
+        { licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version }
+    ) {
+        if (previousLicenseKeyGroup) {
+            return putLicenseKeyGroup(
+                licenseModelId,
+                licenseKeyGroup,
+                version
+            ).then(() => {
+                dispatch({
+                    type: licenseKeyGroupsConstants.EDIT_LICENSE_KEY_GROUP,
+                    licenseKeyGroup
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        } else {
+            return postLicenseKeyGroup(
+                licenseModelId,
+                licenseKeyGroup,
+                version
+            ).then(response => {
+                dispatch({
+                    type: licenseKeyGroupsConstants.ADD_LICENSE_KEY_GROUP,
+                    licenseKeyGroup: {
+                        ...licenseKeyGroup,
+                        referencingFeatureGroups: [],
+                        id: response.value
+                    }
+                });
+                return ItemsHelper.checkItemStatus(dispatch, {
+                    itemId: licenseModelId,
+                    versionId: version.id
+                });
+            });
+        }
+    },
+
+    deleteLicenseKeyGroup(
+        dispatch,
+        { licenseModelId, licenseKeyGroupId, version }
+    ) {
+        return deleteLicenseKeyGroup(
+            licenseModelId,
+            licenseKeyGroupId,
+            version
+        ).then(() => {
+            dispatch({
+                type: licenseKeyGroupsConstants.DELETE_LICENSE_KEY_GROUP,
+                licenseKeyGroupId
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    },
+
+    hideDeleteConfirm(dispatch) {
+        dispatch({
+            type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
+            licenseKeyGroupToDelete: false
+        });
+    },
+
+    openDeleteLicenseAgreementConfirm(dispatch, { licenseKeyGroup }) {
+        dispatch({
+            type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
+            licenseKeyGroupToDelete: licenseKeyGroup
+        });
+    },
+
+    fetchLimits(dispatch, { licenseModelId, version, licenseKeyGroup }) {
+        return fetchLimitsList(
+            licenseModelId,
+            licenseKeyGroup.id,
+            version
+        ).then(response => {
+            dispatch({
+                type:
+                    licenseKeyGroupsConstants.licenseKeyGroupsEditor
+                        .LIMITS_LIST_LOADED,
+                response
+            });
+        });
+    },
 
+    submitLimit(dispatch, { licenseModelId, version, licenseKeyGroup, limit }) {
+        const promise = limit.id
+            ? putLimit(licenseModelId, licenseKeyGroup.id, version, limit)
+            : postLimit(licenseModelId, licenseKeyGroup.id, version, limit);
+        return promise.then(() => {
+            dispatch({
+                type: limitEditorActions.CLOSE
+            });
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                licenseKeyGroup
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    },
 
+    deleteLimit(dispatch, { licenseModelId, version, licenseKeyGroup, limit }) {
+        return deleteLimit(
+            licenseModelId,
+            licenseKeyGroup.id,
+            version,
+            limit.id
+        ).then(() => {
+            this.fetchLimits(dispatch, {
+                licenseModelId,
+                version,
+                licenseKeyGroup
+            });
+            return ItemsHelper.checkItemStatus(dispatch, {
+                itemId: licenseModelId,
+                versionId: version.id
+            });
+        });
+    }
 };
index c376cb3..aad0a0b 100644 (file)
  */
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import InputOptions, {
+    other as optionInputOther
+} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export const actionTypes = keyMirror({
-
-       LICENSE_KEY_GROUPS_LIST_LOADED: null,
-       DELETE_LICENSE_KEY_GROUP: null,
-       EDIT_LICENSE_KEY_GROUP: null,
-       ADD_LICENSE_KEY_GROUP: null,
-       LICENSE_KEY_GROUPS_DELETE_CONFIRM: null,
-       licenseKeyGroupsEditor: {
-               OPEN: null,
-               CLOSE: null,
-               DATA_CHANGED: null,
-               LIMITS_LIST_LOADED: null
-       }
+    LICENSE_KEY_GROUPS_LIST_LOADED: null,
+    DELETE_LICENSE_KEY_GROUP: null,
+    EDIT_LICENSE_KEY_GROUP: null,
+    ADD_LICENSE_KEY_GROUP: null,
+    LICENSE_KEY_GROUPS_DELETE_CONFIRM: null,
+    licenseKeyGroupsEditor: {
+        OPEN: null,
+        CLOSE: null,
+        DATA_CHANGED: null,
+        LIMITS_LIST_LOADED: null
+    }
 });
 
 export const defaultState = {
-       licenseKeyGroupsEditor: {
-               type: '',
-               operationalScope: {choices: [], other: ''}
-       }
+    licenseKeyGroupsEditor: {
+        type: '',
+        operationalScope: { choices: [], other: '' }
+    }
 };
 
 export const LKG_FORM_NAME = 'LKGFORM';
 
 export const optionsInputValues = {
-       OPERATIONAL_SCOPE: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Network_Wide', title: 'Network Wide'},
-               {enum: 'Availability_Zone', title: 'Availability Zone'},
-               {enum: 'Data_Center', title: 'Data Center'},
-               {enum: 'Tenant', title: 'Tenant'},
-               {enum: 'VM', title: 'VM'},
-               {enum: 'CPU', title: 'CPU'},
-               {enum: 'Core', title: 'Core'}
-       ],
-       TYPE: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Universal', title: 'Universal'},
-               {enum: 'Unique', title: 'Unique'},
-               {enum: 'One_Time', title: 'One Time'}
-       ]
+    OPERATIONAL_SCOPE: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Network_Wide', title: 'Network Wide' },
+        { enum: 'Availability_Zone', title: 'Availability Zone' },
+        { enum: 'Data_Center', title: 'Data Center' },
+        { enum: 'Tenant', title: 'Tenant' },
+        { enum: 'VM', title: 'VM' },
+        { enum: 'CPU', title: 'CPU' },
+        { enum: 'Core', title: 'Core' }
+    ],
+    TYPE: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Universal', title: 'Universal' },
+        { enum: 'Unique', title: 'Unique' },
+        { enum: 'One_Time', title: 'One Time' }
+    ]
 };
 
-export const extractValue = (item) => {
-       if (item === undefined) {return '';} //TODO fix it later
+export const extractValue = item => {
+    if (item === undefined) {
+        return '';
+    } //TODO fix it later
 
-       return  item ? item === optionInputOther.OTHER ? item : InputOptions.getTitleByName(optionsInputValues, item) : '';
+    return item
+        ? item === optionInputOther.OTHER
+          ? item
+          : InputOptions.getTitleByName(optionsInputValues, item)
+        : '';
 };
 
-export const getOperationalScopes = (operationalScope) => {
-       if(operationalScope.choices.toString() === i18n(optionInputOther.OTHER) && operationalScope.other !== '') {
-               return operationalScope.other;
-       }
-       else {
-               let allOpScopes = '';
-               for (let opScope of operationalScope.choices) {
-                       allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`;
-               }
-               return allOpScopes;
-       }
+export const getOperationalScopes = operationalScope => {
+    if (
+        operationalScope.choices.toString() === i18n(optionInputOther.OTHER) &&
+        operationalScope.other !== ''
+    ) {
+        return operationalScope.other;
+    } else {
+        let allOpScopes = '';
+        for (let opScope of operationalScope.choices) {
+            allOpScopes +=
+                allOpScopes === ''
+                    ? InputOptions.getTitleByName(optionsInputValues, opScope)
+                    : `, ${InputOptions.getTitleByName(
+                          optionsInputValues,
+                          opScope
+                      )}`;
+        }
+        return allOpScopes;
+    }
 };
 
 export const tabIds = {
-       GENERAL: 'GENERAL',
-       SP_LIMITS: 'SP_LIMITS',
-       VENDOR_LIMITS: 'VENDOR_LIMITS',
-       ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
+    GENERAL: 'GENERAL',
+    SP_LIMITS: 'SP_LIMITS',
+    VENDOR_LIMITS: 'VENDOR_LIMITS',
+    ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
 };
index 028fa9d..fa62bba 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
 import LicenseKeyGroupsEditorView from './LicenseKeyGroupsEditorView.jsx';
 import LimitEditorActionHelper from '../limits/LimitEditorActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
+const mapStateToProps = ({ licenseModel: { licenseKeyGroup } }) => {
+    let {
+        data,
+        genericFieldInfo,
+        formReady,
+        limitsList
+    } = licenseKeyGroup.licenseKeyGroupsEditor;
 
+    let previousData,
+        LKGNames = {};
+    const licenseKeyGroupId = data ? data.id : null;
+    if (licenseKeyGroupId) {
+        previousData = licenseKeyGroup.licenseKeyGroupsList.find(
+            licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId
+        );
+    }
 
-       let {data, genericFieldInfo, formReady, limitsList} = licenseKeyGroup.licenseKeyGroupsEditor;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let previousData, LKGNames = {};
-       const licenseKeyGroupId = data ? data.id : null;
-       if(licenseKeyGroupId) {
-               previousData = licenseKeyGroup.licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId);
-       }
+    const list = licenseKeyGroup.licenseKeyGroupsList;
+    for (let i = 0; i < list.length; i++) {
+        LKGNames[list[i].name.toLowerCase()] = list[i].id;
+    }
 
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-
-       const list = licenseKeyGroup.licenseKeyGroupsList;
-       for (let i = 0; i < list.length; i++) {
-               LKGNames[list[i].name.toLowerCase()] = list[i].id;
-       }
-
-       return {
-               data,
-               previousData,
-               genericFieldInfo,
-               isFormValid,
-               formReady,
-               LKGNames,
-               limitsList
-       };
+    return {
+        data,
+        previousData,
+        genericFieldInfo,
+        isFormValid,
+        formReady,
+        LKGNames,
+        limitsList
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onCancel: () => LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch),
-               onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup, keepOpen}) => {
-                       if (!keepOpen) {LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch);}
-                       LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version});
-               },
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName),
-               onCloseLimitEditor: () => LimitEditorActionHelper.closeLimitsEditor(dispatch),
-               onOpenLimitEditor: (limit) => LimitEditorActionHelper.openLimitsEditor(dispatch, {limit})
-       };
+const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onCancel: () =>
+            LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch),
+        onSubmit: ({ previousLicenseKeyGroup, licenseKeyGroup, keepOpen }) => {
+            if (!keepOpen) {
+                LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(
+                    dispatch
+                );
+            }
+            LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {
+                licenseModelId,
+                previousLicenseKeyGroup,
+                licenseKeyGroup,
+                version
+            });
+        },
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName),
+        onCloseLimitEditor: () =>
+            LimitEditorActionHelper.closeLimitsEditor(dispatch),
+        onOpenLimitEditor: limit =>
+            LimitEditorActionHelper.openLimitsEditor(dispatch, { limit })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseKeyGroupsEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseKeyGroupsEditorView
+);
index b1a22f3..e948e9c 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, defaultState, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js';
+import {
+    actionTypes,
+    defaultState,
+    LKG_FORM_NAME
+} from './LicenseKeyGroupsConstants.js';
 import moment from 'moment';
-import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.licenseKeyGroupsEditor.OPEN:
-                       let licenseKeyGroupData = {...action.licenseKeyGroup};
-                       let {startDate, expiryDate} = licenseKeyGroupData;
-                       if (startDate) {
-                               licenseKeyGroupData.startDate = moment(startDate, DATE_FORMAT).format(DATE_FORMAT);
-                       }
-                       if (expiryDate) {
-                               licenseKeyGroupData.expiryDate = moment(expiryDate, DATE_FORMAT).format(DATE_FORMAT);
-                       }
-                       return {
-                               ...state,
-                               data: action.licenseKeyGroup ? licenseKeyGroupData : defaultState.licenseKeyGroupsEditor,
-                               formReady: null,
-                               formName: LKG_FORM_NAME,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
-                                       },
-                                       'type' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       'operationalScope' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'thresholdUnits' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'thresholdValue' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'increments' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 120}]
-                                       },
-                                       'startDate': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'expiryDate': {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               }
-                       };
-               case actionTypes.licenseKeyGroupsEditor.LIMITS_LIST_LOADED:
-                       return {
-                               ...state,
-                               limitsList: action.response.results
-                       };      
-               case actionTypes.licenseKeyGroupsEditor.CLOSE:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.licenseKeyGroupsEditor.OPEN:
+            let licenseKeyGroupData = { ...action.licenseKeyGroup };
+            let { startDate, expiryDate } = licenseKeyGroupData;
+            if (startDate) {
+                licenseKeyGroupData.startDate = moment(
+                    startDate,
+                    DATE_FORMAT
+                ).format(DATE_FORMAT);
+            }
+            if (expiryDate) {
+                licenseKeyGroupData.expiryDate = moment(
+                    expiryDate,
+                    DATE_FORMAT
+                ).format(DATE_FORMAT);
+            }
+            return {
+                ...state,
+                data: action.licenseKeyGroup
+                    ? licenseKeyGroupData
+                    : defaultState.licenseKeyGroupsEditor,
+                formReady: null,
+                formName: LKG_FORM_NAME,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ]
+                    },
+                    type: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    operationalScope: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    thresholdUnits: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    thresholdValue: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    increments: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 120 }]
+                    },
+                    startDate: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    expiryDate: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                }
+            };
+        case actionTypes.licenseKeyGroupsEditor.LIMITS_LIST_LOADED:
+            return {
+                ...state,
+                limitsList: action.response.results
+            };
+        case actionTypes.licenseKeyGroupsEditor.CLOSE:
+            return {};
+        default:
+            return state;
+    }
 };
index 7cbab61..a820f28 100644 (file)
@@ -26,328 +26,498 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME, tabIds} from './LicenseKeyGroupsConstants.js';
-import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
-import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import {
+    optionsInputValues as licenseKeyGroupOptionsInputValues,
+    LKG_FORM_NAME,
+    tabIds
+} from './LicenseKeyGroupsConstants.js';
+import { optionsInputValues as LicenseModelOptionsInputValues } from '../LicenseModelConstants.js';
+import {
+    validateStartDate,
+    thresholdValueValidation
+} from '../LicenseModelValidations.js';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 
-import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 import LicenseKeyGroupsLimits from './LicenseKeyGroupsLimits.js';
-import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
+import {
+    limitType,
+    NEW_LIMIT_TEMP_ID
+} from '../limits/LimitEditorConstants.js';
 
- const LicenseKeyGroupPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       increments: PropTypes.string,
-       operationalScope: PropTypes.shape({
-               choices: PropTypes.array,
-               other: PropTypes.string
-       }),
-       type: PropTypes.string,
-        thresholdUnits: PropTypes.string,
-        thresholdValue: PropTypes.number,
-        startDate: PropTypes.string,
-        expiryDate: PropTypes.string
+const LicenseKeyGroupPropType = PropTypes.shape({
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    increments: PropTypes.string,
+    operationalScope: PropTypes.shape({
+        choices: PropTypes.array,
+        other: PropTypes.string
+    }),
+    type: PropTypes.string,
+    thresholdUnits: PropTypes.string,
+    thresholdValue: PropTypes.number,
+    startDate: PropTypes.string,
+    expiryDate: PropTypes.string
 });
 
-const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateStartDate, thresholdValueValidation}) => {
-       let {name, description, increments, operationalScope, type, thresholdUnits, thresholdValue, startDate, expiryDate} = data;
-       return (
-               <GridSection hasLostColSet>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})}
-                                       label={i18n('Name')}
-                                       data-test-id='create-lkg-name'
-                                       value={name}
-                                       isValid={genericFieldInfo.name.isValid}
-                                       errorText={genericFieldInfo.name.errorText}
-                                       isRequired={true}
-                                       type='text'/>
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                               <InputOptions
-                                       onInputChange={()=>{}}
-                                       isMultiSelect={true}
-                                       onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
-                                               LKG_FORM_NAME)}
-                                       onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
-                                               other: operationalScope}}, LKG_FORM_NAME)}
-                                       label={i18n('Operational Scope')}
-                                       data-test-id='create-lkg-operational-scope'
-                                       type='select'
-                                       multiSelectedEnum={operationalScope && operationalScope.choices}
-                                       otherValue={operationalScope && operationalScope.other}
-                                       values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}
-                                       isValid={genericFieldInfo.operationalScope.isValid}
-                                       errorText={genericFieldInfo.operationalScope.errorText} />
-                       </GridItem>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       onChange={description => onDataChanged({description}, LKG_FORM_NAME)}
-                                       label={i18n('Description')}
-                                       data-test-id='create-lkg-description'
-                                       value={description}
-                                       isValid={genericFieldInfo.description.isValid}
-                                       errorText={genericFieldInfo.description.errorText}
-                                       type='textarea'
-                                       overlayPos='bottom' />
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                               <Input
-                                       isRequired={true}
-                                       onChange={e => { const selectedIndex = e.target.selectedIndex;
-                                               const val = e.target.options[selectedIndex].value;
-                                               onDataChanged({type: val}, LKG_FORM_NAME);}}
-                                       value={type}
-                                       label={i18n('Type')}
-                                       data-test-id='create-lkg-type'
-                                       isValid={genericFieldInfo.type.isValid}
-                                       errorText={genericFieldInfo.type.errorText}
-                                       groupClassName='bootstrap-input-options'
-                                       className='input-options-select'
-                                       overlayPos='bottom'
-                                       type='select' >
-                                       {
-                                               licenseKeyGroupOptionsInputValues.TYPE.map(type =>
-                                               (<option key={type.enum} value={type.enum}>{type.title}</option>))
-                                       }
-                               </Input>
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       onChange={e => {
-                                               // setting the unit to the correct value
-                                               const selectedIndex = e.target.selectedIndex;
-                                               const val = e.target.options[selectedIndex].value;
-                                               onDataChanged({thresholdUnits: val}, LKG_FORM_NAME);
-                                               // TODO make sure that the value is valid too
-                                               onDataChanged({thresholdValue: thresholdValue}, LKG_FORM_NAME,{thresholdValue : thresholdValueValidation});}
-
-                                       }
-                                       value={thresholdUnits}
-                                       label={i18n('Threshold Units')}
-                                       data-test-id='create-ep-threshold-units'
-                                       isValid={genericFieldInfo.thresholdUnits.isValid}
-                                       errorText={genericFieldInfo.thresholdUnits.errorText}
-                                       groupClassName='bootstrap-input-options'
-                                       className='input-options-select'
-                                       type='select' >
-                                       {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
-                                               <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                               </Input>
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       className='entitlement-pools-form-row-threshold-value'
-                                       onChange={thresholdValue => onDataChanged({thresholdValue}, LKG_FORM_NAME,
-                                               {thresholdValue : thresholdValueValidation})}
-                                       label={i18n('Threshold Value')}
-                                       isValid={genericFieldInfo.thresholdValue.isValid}
-                                       errorText={genericFieldInfo.thresholdValue.errorText}
-                                       data-test-id='create-ep-threshold-value'
-                                       value={thresholdValue}
-                                       type='text'/>
-                       </GridItem>
-                               <GridItem>
-                               <Input
-                                       type='date'
-                                       label={i18n('Start Date')}
-                                       value={startDate}
-                                       dateFormat={DATE_FORMAT}
-                                       startDate={startDate}
-                                       endDate={expiryDate}
-                                       onChange={startDate => onDataChanged(
-                                               {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
-                                               LKG_FORM_NAME,
-                                               {startDate: validateStartDate}
-                                       )}
-                                       isValid={genericFieldInfo.startDate.isValid}
-                                       errorText={genericFieldInfo.startDate.errorText}
-                                       selectsStart/>
-                       </GridItem>
-                       <GridItem lastColInRow>
-                               <Input
-                                       type='date'
-                                       label={i18n('Expiry Date')}
-                                       value={expiryDate}
-                                       dateFormat={DATE_FORMAT}
-                                       startDate={startDate}
-                                       endDate={expiryDate}
-                                       onChange={expiryDate => {
-                                               onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, LKG_FORM_NAME);
-                                               onDataChanged({startDate}, LKG_FORM_NAME, {startDate: validateStartDate});
-                                       }}
-                                       isValid={genericFieldInfo.expiryDate.isValid}
-                                       errorText={genericFieldInfo.expiryDate.errorText}
-                                       selectsEnd/>
-                       </GridItem>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       onChange={increments => onDataChanged({increments}, LKG_FORM_NAME)}
-                                       label={i18n('Increments')}
-                                       value={increments}
-                                       data-test-id='create-ep-increments'
-                                       type='text'/>
-                       </GridItem>
-               </GridSection>
-       );
+const LicenseKeyGroupFormContent = ({
+    data,
+    onDataChanged,
+    genericFieldInfo,
+    validateName,
+    validateStartDate,
+    thresholdValueValidation
+}) => {
+    let {
+        name,
+        description,
+        increments,
+        operationalScope,
+        type,
+        thresholdUnits,
+        thresholdValue,
+        startDate,
+        expiryDate
+    } = data;
+    return (
+        <GridSection hasLostColSet>
+            <GridItem colSpan={2}>
+                <Input
+                    onChange={name =>
+                        onDataChanged({ name }, LKG_FORM_NAME, {
+                            name: validateName
+                        })
+                    }
+                    label={i18n('Name')}
+                    data-test-id="create-lkg-name"
+                    value={name}
+                    isValid={genericFieldInfo.name.isValid}
+                    errorText={genericFieldInfo.name.errorText}
+                    isRequired={true}
+                    type="text"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <InputOptions
+                    onInputChange={() => {}}
+                    isMultiSelect={true}
+                    onEnumChange={operationalScope =>
+                        onDataChanged(
+                            {
+                                operationalScope: {
+                                    choices: operationalScope,
+                                    other: ''
+                                }
+                            },
+                            LKG_FORM_NAME
+                        )
+                    }
+                    onOtherChange={operationalScope =>
+                        onDataChanged(
+                            {
+                                operationalScope: {
+                                    choices: [optionInputOther.OTHER],
+                                    other: operationalScope
+                                }
+                            },
+                            LKG_FORM_NAME
+                        )
+                    }
+                    label={i18n('Operational Scope')}
+                    data-test-id="create-lkg-operational-scope"
+                    type="select"
+                    multiSelectedEnum={
+                        operationalScope && operationalScope.choices
+                    }
+                    otherValue={operationalScope && operationalScope.other}
+                    values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}
+                    isValid={genericFieldInfo.operationalScope.isValid}
+                    errorText={genericFieldInfo.operationalScope.errorText}
+                />
+            </GridItem>
+            <GridItem colSpan={2}>
+                <Input
+                    onChange={description =>
+                        onDataChanged({ description }, LKG_FORM_NAME)
+                    }
+                    label={i18n('Description')}
+                    data-test-id="create-lkg-description"
+                    value={description}
+                    isValid={genericFieldInfo.description.isValid}
+                    errorText={genericFieldInfo.description.errorText}
+                    type="textarea"
+                    overlayPos="bottom"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <Input
+                    isRequired={true}
+                    onChange={e => {
+                        const selectedIndex = e.target.selectedIndex;
+                        const val = e.target.options[selectedIndex].value;
+                        onDataChanged({ type: val }, LKG_FORM_NAME);
+                    }}
+                    value={type}
+                    label={i18n('Type')}
+                    data-test-id="create-lkg-type"
+                    isValid={genericFieldInfo.type.isValid}
+                    errorText={genericFieldInfo.type.errorText}
+                    groupClassName="bootstrap-input-options"
+                    className="input-options-select"
+                    overlayPos="bottom"
+                    type="select">
+                    {licenseKeyGroupOptionsInputValues.TYPE.map(type => (
+                        <option key={type.enum} value={type.enum}>
+                            {type.title}
+                        </option>
+                    ))}
+                </Input>
+            </GridItem>
+            <GridItem>
+                <Input
+                    onChange={e => {
+                        // setting the unit to the correct value
+                        const selectedIndex = e.target.selectedIndex;
+                        const val = e.target.options[selectedIndex].value;
+                        onDataChanged({ thresholdUnits: val }, LKG_FORM_NAME);
+                        // TODO make sure that the value is valid too
+                        onDataChanged(
+                            { thresholdValue: thresholdValue },
+                            LKG_FORM_NAME,
+                            {
+                                thresholdValue: thresholdValueValidation
+                            }
+                        );
+                    }}
+                    value={thresholdUnits}
+                    label={i18n('Threshold Units')}
+                    data-test-id="create-ep-threshold-units"
+                    isValid={genericFieldInfo.thresholdUnits.isValid}
+                    errorText={genericFieldInfo.thresholdUnits.errorText}
+                    groupClassName="bootstrap-input-options"
+                    className="input-options-select"
+                    type="select">
+                    {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(
+                        mtype => (
+                            <option key={mtype.enum} value={mtype.enum}>{`${
+                                mtype.title
+                            }`}</option>
+                        )
+                    )}
+                </Input>
+            </GridItem>
+            <GridItem>
+                <Input
+                    className="entitlement-pools-form-row-threshold-value"
+                    onChange={thresholdValue =>
+                        onDataChanged({ thresholdValue }, LKG_FORM_NAME, {
+                            thresholdValue: thresholdValueValidation
+                        })
+                    }
+                    label={i18n('Threshold Value')}
+                    isValid={genericFieldInfo.thresholdValue.isValid}
+                    errorText={genericFieldInfo.thresholdValue.errorText}
+                    data-test-id="create-ep-threshold-value"
+                    value={thresholdValue}
+                    type="text"
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    type="date"
+                    label={i18n('Start Date')}
+                    value={startDate}
+                    dateFormat={DATE_FORMAT}
+                    startDate={startDate}
+                    endDate={expiryDate}
+                    onChange={startDate =>
+                        onDataChanged(
+                            {
+                                startDate: startDate
+                                    ? startDate.format(DATE_FORMAT)
+                                    : ''
+                            },
+                            LKG_FORM_NAME,
+                            { startDate: validateStartDate }
+                        )
+                    }
+                    isValid={genericFieldInfo.startDate.isValid}
+                    errorText={genericFieldInfo.startDate.errorText}
+                    selectsStart
+                />
+            </GridItem>
+            <GridItem lastColInRow>
+                <Input
+                    type="date"
+                    label={i18n('Expiry Date')}
+                    value={expiryDate}
+                    dateFormat={DATE_FORMAT}
+                    startDate={startDate}
+                    endDate={expiryDate}
+                    onChange={expiryDate => {
+                        onDataChanged(
+                            {
+                                expiryDate: expiryDate
+                                    ? expiryDate.format(DATE_FORMAT)
+                                    : ''
+                            },
+                            LKG_FORM_NAME
+                        );
+                        onDataChanged({ startDate }, LKG_FORM_NAME, {
+                            startDate: validateStartDate
+                        });
+                    }}
+                    isValid={genericFieldInfo.expiryDate.isValid}
+                    errorText={genericFieldInfo.expiryDate.errorText}
+                    selectsEnd
+                />
+            </GridItem>
+            <GridItem colSpan={2}>
+                <Input
+                    onChange={increments =>
+                        onDataChanged({ increments }, LKG_FORM_NAME)
+                    }
+                    label={i18n('Increments')}
+                    value={increments}
+                    data-test-id="create-ep-increments"
+                    type="text"
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 class LicenseKeyGroupsEditorView extends React.Component {
-       static propTypes = {
-               data: LicenseKeyGroupPropType,
-               previousData: LicenseKeyGroupPropType,
-               LKGNames: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
-
-       static defaultProps = {
-               data: {}
-       };
-
-       componentDidUpdate(prevProps) {
-               if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
-                       this.submit();
-               }
-       }
+    static propTypes = {
+        data: LicenseKeyGroupPropType,
+        previousData: LicenseKeyGroupPropType,
+        LKGNames: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       state = {
-               localFeatureGroupsListFilter: '',
-               selectedTab: tabIds.GENERAL,
-               selectedLimit: ''
-       };
+    static defaultProps = {
+        data: {}
+    };
 
-       render() {
-               let {data = {}, onDataChanged, isReadOnlyMode, onCloseLimitEditor, genericFieldInfo, limitsList = []} = this.props;
-               let {selectedTab} = this.state;
-               const isTabsDisabled = !data.id || !this.props.isFormValid;
-               return (
-                       <div className='license-keygroup-editor'>
-                               <Tabs
-                                       type='menu'
-                                       activeTab={selectedTab}
-                                       onTabClick={(tabIndex)=>{
-                                               if (tabIndex === tabIds.ADD_LIMIT_BUTTON)  {
-                                                       this.onAddLimit();
-                                               } else {
-                                                       this.setState({selectedTab: tabIndex});
-                                                       onCloseLimitEditor();
-                                                       this.setState({selectedLimit: ''});
-                                               }
-                                       }}
-                                       invalidTabs={[]}>
-                                       <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
-                                               { genericFieldInfo &&
-                                                       <Form
-                                                               ref='validationForm'
-                                                               hasButtons={false}
-                                                               isValid={this.props.isFormValid}
-                                                               formReady={this.props.formReady}
-                                                               onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
-                                                               labledButtons={true}
-                                                               isReadOnlyMode={isReadOnlyMode}
-                                                               className='license-model-form license-key-groups-form'>
-                                                                       <LicenseKeyGroupFormContent
-                                                                               data={data}
-                                                                               onDataChanged={onDataChanged}
-                                                                               genericFieldInfo={genericFieldInfo}
-                                                                               validateName={(value)=> this.validateName(value)}
-                                                                               validateStartDate={(value, state)=> validateStartDate(value, state)}
-                                                                               thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
-                                                       </Form>}
+    componentDidUpdate(prevProps) {
+        if (
+            this.props.formReady &&
+            this.props.formReady !== prevProps.formReady
+        ) {
+            // if form validation succeeded -> continue with submit
+            this.submit();
+        }
+    }
 
-                                       </Tab>
-                                       <Tab tabId={tabIds.SP_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('SP Limits')}>
-                                               {selectedTab === tabIds.SP_LIMITS &&
-                                                       <LicenseKeyGroupsLimits
-                                                               limitType={limitType.SERVICE_PROVIDER}
-                                                               limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
-                                                               selectedLimit={this.state.selectedLimit}
-                                                               onCloseLimitEditor={() => this.onCloseLimitEditor()}
-                                                               onSelectLimit={limit => this.onSelectLimit(limit)}
-                                                               isReadOnlyMode={isReadOnlyMode} />}
-                                       </Tab>
-                                       <Tab tabId={tabIds.VENDOR_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('Vendor Limits')}>
-                                               {selectedTab === tabIds.VENDOR_LIMITS &&
-                                                       <LicenseKeyGroupsLimits
-                                                               limitType={limitType.VENDOR}
-                                                               limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
-                                                               selectedLimit={this.state.selectedLimit}
-                                                               onCloseLimitEditor={() => this.onCloseLimitEditor()}
-                                                               onSelectLimit={limit => this.onSelectLimit(limit)}
-                                                               isReadOnlyMode={isReadOnlyMode} />}
-                                       </Tab>
-                                       {selectedTab !== tabIds.GENERAL ?
-                                                       <Button
-                                                               className='add-limit-button'
-                                                               tabId={tabIds.ADD_LIMIT_BUTTON}
-                                                               btnType='link'
-                                                               iconName='plus'
-                                                               disabled={this.state.selectedLimit || isReadOnlyMode}>
-                                                               {i18n('Add Limit')}
-                                                       </Button>
-                                               :
-                                                       <div key='empty_lm_tab_key'></div> // Render empty div to not break tabs
-                                       }
-                               </Tabs>
+    state = {
+        localFeatureGroupsListFilter: '',
+        selectedTab: tabIds.GENERAL,
+        selectedLimit: ''
+    };
 
-                               <GridSection className='license-model-modal-buttons license-key-group-editor-buttons'>
-                                       {!this.state.selectedLimit &&
-                                               <Button btnType='default' disabled={!this.props.isFormValid || isReadOnlyMode} onClick={() => this.submit()} type='reset'>
-                                                       {i18n('Save')}
-                                               </Button>
-                                       }
-                                       <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
-                                               {i18n('Cancel')}
-                                       </Button>
-                               </GridSection>
-                       </div>
+    render() {
+        let {
+            data = {},
+            onDataChanged,
+            isReadOnlyMode,
+            onCloseLimitEditor,
+            genericFieldInfo,
+            limitsList = []
+        } = this.props;
+        let { selectedTab } = this.state;
+        const isTabsDisabled = !data.id || !this.props.isFormValid;
+        return (
+            <div className="license-keygroup-editor">
+                <Tabs
+                    type="menu"
+                    activeTab={selectedTab}
+                    onTabClick={tabIndex => {
+                        if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
+                            this.onAddLimit();
+                        } else {
+                            this.setState({ selectedTab: tabIndex });
+                            onCloseLimitEditor();
+                            this.setState({ selectedLimit: '' });
+                        }
+                    }}
+                    invalidTabs={[]}>
+                    <Tab
+                        tabId={tabIds.GENERAL}
+                        data-test-id="general-tab"
+                        title={i18n('General')}>
+                        {genericFieldInfo && (
+                            <Form
+                                ref="validationForm"
+                                hasButtons={false}
+                                isValid={this.props.isFormValid}
+                                formReady={this.props.formReady}
+                                onValidateForm={() =>
+                                    this.props.onValidateForm(LKG_FORM_NAME)
+                                }
+                                labledButtons={true}
+                                isReadOnlyMode={isReadOnlyMode}
+                                className="license-model-form license-key-groups-form">
+                                <LicenseKeyGroupFormContent
+                                    data={data}
+                                    onDataChanged={onDataChanged}
+                                    genericFieldInfo={genericFieldInfo}
+                                    validateName={value =>
+                                        this.validateName(value)
+                                    }
+                                    validateStartDate={(value, state) =>
+                                        validateStartDate(value, state)
+                                    }
+                                    thresholdValueValidation={(value, state) =>
+                                        thresholdValueValidation(value, state)
+                                    }
+                                />
+                            </Form>
+                        )}
+                    </Tab>
+                    <Tab
+                        tabId={tabIds.SP_LIMITS}
+                        disabled={isTabsDisabled}
+                        data-test-id="general-tab"
+                        title={i18n('SP Limits')}>
+                        {selectedTab === tabIds.SP_LIMITS && (
+                            <LicenseKeyGroupsLimits
+                                limitType={limitType.SERVICE_PROVIDER}
+                                limitsList={limitsList.filter(
+                                    item =>
+                                        item.type === limitType.SERVICE_PROVIDER
+                                )}
+                                selectedLimit={this.state.selectedLimit}
+                                onCloseLimitEditor={() =>
+                                    this.onCloseLimitEditor()
+                                }
+                                onSelectLimit={limit =>
+                                    this.onSelectLimit(limit)
+                                }
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    </Tab>
+                    <Tab
+                        tabId={tabIds.VENDOR_LIMITS}
+                        disabled={isTabsDisabled}
+                        data-test-id="general-tab"
+                        title={i18n('Vendor Limits')}>
+                        {selectedTab === tabIds.VENDOR_LIMITS && (
+                            <LicenseKeyGroupsLimits
+                                limitType={limitType.VENDOR}
+                                limitsList={limitsList.filter(
+                                    item => item.type === limitType.VENDOR
+                                )}
+                                selectedLimit={this.state.selectedLimit}
+                                onCloseLimitEditor={() =>
+                                    this.onCloseLimitEditor()
+                                }
+                                onSelectLimit={limit =>
+                                    this.onSelectLimit(limit)
+                                }
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    </Tab>
+                    {selectedTab !== tabIds.GENERAL ? (
+                        <Button
+                            className="add-limit-button"
+                            tabId={tabIds.ADD_LIMIT_BUTTON}
+                            btnType="link"
+                            iconName="plus"
+                            disabled={
+                                this.state.selectedLimit || isReadOnlyMode
+                            }>
+                            {i18n('Add Limit')}
+                        </Button>
+                    ) : (
+                        <div key="empty_lm_tab_key" />
+                    ) // Render empty div to not break tabs
+                    }
+                </Tabs>
 
-               );
-       }
+                <GridSection className="license-model-modal-buttons license-key-group-editor-buttons">
+                    {!this.state.selectedLimit && (
+                        <Button
+                            btnType="default"
+                            disabled={!this.props.isFormValid || isReadOnlyMode}
+                            onClick={() => this.submit()}
+                            type="reset">
+                            {i18n('Save')}
+                        </Button>
+                    )}
+                    <Button
+                        btnType={
+                            this.state.selectedLimit ? 'default' : 'outline'
+                        }
+                        onClick={() => this.props.onCancel()}
+                        type="reset">
+                        {i18n('Cancel')}
+                    </Button>
+                </GridSection>
+            </div>
+        );
+    }
 
-       submit() {
-               const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup, formReady, onValidateForm, onSubmit} = this.props;
-               if (!formReady) {
-                       onValidateForm(LKG_FORM_NAME);
-               } else {
-                       onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
-               }
-       }
+    submit() {
+        const {
+            data: licenseKeyGroup,
+            previousData: previousLicenseKeyGroup,
+            formReady,
+            onValidateForm,
+            onSubmit
+        } = this.props;
+        if (!formReady) {
+            onValidateForm(LKG_FORM_NAME);
+        } else {
+            onSubmit({ licenseKeyGroup, previousLicenseKeyGroup });
+        }
+    }
 
-       validateName(value) {
-               const {data: {id}, LKGNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames});
+    validateName(value) {
+        const { data: { id }, LKGNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: LKGNames
+        });
 
-               return !isExists ?  {isValid: true, errorText: ''} :
-                       {isValid: false, errorText: i18n('License key group by the name \'' + value + '\' already exists. License key group name must be unique')};
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "License key group by the name '" +
+                          value +
+                          "' already exists. License key group name must be unique"
+                  )
+              };
+    }
 
-       onSelectLimit(limit) {
-               if (limit.id === this.state.selectedLimit) {
-                       this.setState({selectedLimit: ''});
-                       return;
-               }
-               this.setState({selectedLimit: limit.id});
-               this.props.onOpenLimitEditor(limit);
-       }
+    onSelectLimit(limit) {
+        if (limit.id === this.state.selectedLimit) {
+            this.setState({ selectedLimit: '' });
+            return;
+        }
+        this.setState({ selectedLimit: limit.id });
+        this.props.onOpenLimitEditor(limit);
+    }
 
-       onCloseLimitEditor() {
-               this.setState({selectedLimit: ''});
-               this.props.onCloseLimitEditor();
-       }
+    onCloseLimitEditor() {
+        this.setState({ selectedLimit: '' });
+        this.props.onCloseLimitEditor();
+    }
 
-       onAddLimit() {
-               this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
-               this.props.onOpenLimitEditor();
-       }
+    onAddLimit() {
+        this.setState({ selectedLimit: NEW_LIMIT_TEMP_ID });
+        this.props.onOpenLimitEditor();
+    }
 }
 
 export default LicenseKeyGroupsEditorView;
index bd8f21a..ad14c6c 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as globalModalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as globalModalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import Limits from 'sdc-app/onboarding/licenseModel/limits/Limits.jsx';
 
 import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
 
-const mapStateToProps = ({licenseModel: {licenseKeyGroup: {licenseKeyGroupsEditor: {data}}, limitEditor}, currentScreen}) => {
-       let  {props: {licenseModelId, version}} = currentScreen;
-       return {
-               parent: data,
-               limitEditor,
-               licenseModelId,
-               version
-       };
+const mapStateToProps = ({
+    licenseModel: {
+        licenseKeyGroup: { licenseKeyGroupsEditor: { data } },
+        limitEditor
+    },
+    currentScreen
+}) => {
+    let { props: { licenseModelId, version } } = currentScreen;
+    return {
+        parent: data,
+        limitEditor,
+        licenseModelId,
+        version
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onSubmit: (limit, licenseKeyGroup, licenseModelId, version) => LicenseKeyGroupsActionHelper.submitLimit(dispatch,
-                       {
-                               limit,
-                               licenseKeyGroup,
-                               licenseModelId,
-                               version}),
-               onDelete: ({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit}) => dispatch({
-                       type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete {name}?', {name: limit.name}),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=> LicenseKeyGroupsActionHelper.deleteLimit(dispatch, {limit, licenseKeyGroup: parent, licenseModelId, version}).then(() =>
-                                       selectedLimit === limit.id && onCloseLimitEditor()
-                               )
-                       }
-               })
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onSubmit: (limit, licenseKeyGroup, licenseModelId, version) =>
+            LicenseKeyGroupsActionHelper.submitLimit(dispatch, {
+                limit,
+                licenseKeyGroup,
+                licenseModelId,
+                version
+            }),
+        onDelete: ({
+            limit,
+            parent,
+            licenseModelId,
+            version,
+            onCloseLimitEditor,
+            selectedLimit
+        }) =>
+            dispatch({
+                type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete {name}?', {
+                        name: limit.name
+                    }),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        LicenseKeyGroupsActionHelper.deleteLimit(dispatch, {
+                            limit,
+                            licenseKeyGroup: parent,
+                            licenseModelId,
+                            version
+                        }).then(
+                            () =>
+                                selectedLimit === limit.id &&
+                                onCloseLimitEditor()
+                        )
+                }
+            })
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(Limits);
index 00c2092..6151c59 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-import {actionTypes as globalMoadlActions}  from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as globalMoadlActions } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
-import LicenseKeyGroupsListEditorView, {generateConfirmationMsg} from './LicenseKeyGroupsListEditorView.jsx';
+import LicenseKeyGroupsListEditorView, {
+    generateConfirmationMsg
+} from './LicenseKeyGroupsListEditorView.jsx';
 
-const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}}) => {
-       let {licenseKeyGroupsList} = licenseKeyGroup;
-       let {data} = licenseKeyGroup.licenseKeyGroupsEditor;
-       let {vendorName} = licenseModelEditor.data;
+const mapStateToProps = ({
+    licenseModel: { licenseKeyGroup, licenseModelEditor }
+}) => {
+    let { licenseKeyGroupsList } = licenseKeyGroup;
+    let { data } = licenseKeyGroup.licenseKeyGroupsEditor;
+    let { vendorName } = licenseModelEditor.data;
 
-       return {
-               vendorName,
-               licenseKeyGroupsList,
-               isDisplayModal: Boolean(data),
-               isModalInEditMode: Boolean(data && data.id)
-       };
+    return {
+        vendorName,
+        licenseKeyGroupsList,
+        isDisplayModal: Boolean(data),
+        isModalInEditMode: Boolean(data && data.id)
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId, version}) => {   
-       return {
-               onAddLicenseKeyGroupClick: () => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch),
-               onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup, licenseModelId, version}),
-               onDeleteLicenseKeyGroupClick: licenseKeyGroup => dispatch({
-                       type: globalMoadlActions.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: generateConfirmationMsg(licenseKeyGroup),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: () => LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroup.id, version})
-                       }
-               })
-       };
+const mapActionsToProps = (dispatch, { licenseModelId, version }) => {
+    return {
+        onAddLicenseKeyGroupClick: () =>
+            LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch),
+        onEditLicenseKeyGroupClick: licenseKeyGroup =>
+            LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {
+                licenseKeyGroup,
+                licenseModelId,
+                version
+            }),
+        onDeleteLicenseKeyGroupClick: licenseKeyGroup =>
+            dispatch({
+                type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: generateConfirmationMsg(licenseKeyGroup),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(
+                            dispatch,
+                            {
+                                licenseModelId,
+                                licenseKeyGroupId: licenseKeyGroup.id,
+                                version
+                            }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseKeyGroupsListEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseKeyGroupsListEditorView
+);
index 5a98b7f..4c8c8ce 100644 (file)
@@ -21,143 +21,205 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 
 import LicenseKeyGroupsEditor from './LicenseKeyGroupsEditor.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
-import {optionsInputValues} from './LicenseKeyGroupsConstants';
+import InputOptions, {
+    other as optionInputOther
+} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { optionsInputValues } from './LicenseKeyGroupsConstants';
 
 class LicenseKeyGroupsListEditorView extends React.Component {
-       static propTypes = {
-               vendorName: PropTypes.string,
-               licenseModelId: PropTypes.string.isRequired,
-               licenseKeyGroupsList: PropTypes.array,
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               isDisplayModal: PropTypes.bool,
-               isModalInEditMode: PropTypes.bool,
-               onAddLicenseKeyGroupClick: PropTypes.func,
-               onEditLicenseKeyGroupClick: PropTypes.func,
-               onDeleteLicenseKeyGroupClick: PropTypes.func
-       };
-
-       static defaultProps = {
-               licenseKeyGroupsList: []
-       };
-
-       state = {
-               localFilter: ''
-       };
-
-       render() {
-               let {licenseModelId, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
-               let {onAddLicenseKeyGroupClick} = this.props;
-               const {localFilter} = this.state;
-
-               return (
-                       <div className='license-model-list-editor license-key-groups-list-editor'>
-                               <ListEditorView
-                                       title={i18n('License Key Groups')}
-                                       plusButtonTitle={i18n('Add License Key Group')}
-                                       onAdd={onAddLicenseKeyGroupClick}
-                                       filterValue={localFilter}
-                                       onFilter={value => this.setState({localFilter: value})}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       {this.filterList().map(licenseKeyGroup => (this.renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode)))}
-                               </ListEditorView>
-                               <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-modal license-key-groups-modal'>
-                                       <Modal.Header>
-                                               <Modal.Title>{`${isModalInEditMode ? i18n('Edit License Key Group') : i18n('Create New License Key Group')}`}</Modal.Title>
-                                       </Modal.Header>
-                                       <Modal.Body>
-                                               {
-                                                       isDisplayModal && (
-                                                               <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
-                                                       )
-                                               }
-                                       </Modal.Body>
-                               </Modal>
-                       </div>
-               );
-       }
-
-       filterList() {
-               let {licenseKeyGroupsList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return licenseKeyGroupsList.filter(({name = '', description = '', operationalScope = '', type = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter) || escape(this.extractValue(operationalScope)).match(filter) || escape(type).match(filter);
-                       });
-               }
-               else {
-                       return licenseKeyGroupsList;
-               }
-       }
-
-       renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode) {
-               let {id, name, description, operationalScope, type} = licenseKeyGroup;
-               let {onEditLicenseKeyGroupClick, onDeleteLicenseKeyGroupClick} = this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               onSelect={() => onEditLicenseKeyGroupClick(licenseKeyGroup)}
-                               onDelete={() => onDeleteLicenseKeyGroupClick(licenseKeyGroup)}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div className='text name'>{name}</div>
-                               </div>
-
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Operational Scope')}</div>
-                                       <div className='text operational-scope'>{operationalScope && this.getOperationalScopes(operationalScope)}</div>
-
-                                       <div className='title'>{i18n('Type')}</div>
-                                       <div className='text type'>{InputOptions.getTitleByName(optionsInputValues, type)}</div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Description')}</div>
-                                       <div className='text description'>{description}</div>
-                               </div>
-                       </ListEditorItemView>
-               );
-       }
-
-       getOperationalScopes(operationalScope) {
-
-               if (operationalScope.choices && operationalScope.choices.toString() === i18n(optionInputOther.OTHER)) {
-                       return operationalScope.other;
-               } else if (operationalScope.choices) {
-                       let allOpScopes = '';
-                       for (let opScope of operationalScope.choices) {
-                               allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`;
-                       }
-                       return allOpScopes;
-               } else {
-                       return '';
-               }
-       }
-
-       extractValue(item) {
-               if (item === undefined) {
-                       return '';
-               } //TODO fix it sooner rather than later
-
-               return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
-       }
+    static propTypes = {
+        vendorName: PropTypes.string,
+        licenseModelId: PropTypes.string.isRequired,
+        licenseKeyGroupsList: PropTypes.array,
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        isDisplayModal: PropTypes.bool,
+        isModalInEditMode: PropTypes.bool,
+        onAddLicenseKeyGroupClick: PropTypes.func,
+        onEditLicenseKeyGroupClick: PropTypes.func,
+        onDeleteLicenseKeyGroupClick: PropTypes.func
+    };
+
+    static defaultProps = {
+        licenseKeyGroupsList: []
+    };
+
+    state = {
+        localFilter: ''
+    };
+
+    render() {
+        let {
+            licenseModelId,
+            isReadOnlyMode,
+            isDisplayModal,
+            isModalInEditMode,
+            version
+        } = this.props;
+        let { onAddLicenseKeyGroupClick } = this.props;
+        const { localFilter } = this.state;
+
+        return (
+            <div className="license-model-list-editor license-key-groups-list-editor">
+                <ListEditorView
+                    title={i18n('License Key Groups')}
+                    plusButtonTitle={i18n('Add License Key Group')}
+                    onAdd={onAddLicenseKeyGroupClick}
+                    filterValue={localFilter}
+                    onFilter={value => this.setState({ localFilter: value })}
+                    isReadOnlyMode={isReadOnlyMode}>
+                    {this.filterList().map(licenseKeyGroup =>
+                        this.renderLicenseKeyGroupListItem(
+                            licenseKeyGroup,
+                            isReadOnlyMode
+                        )
+                    )}
+                </ListEditorView>
+                <Modal
+                    show={isDisplayModal}
+                    bsSize="large"
+                    animation={true}
+                    className="onborading-modal license-model-modal license-key-groups-modal">
+                    <Modal.Header>
+                        <Modal.Title>{`${
+                            isModalInEditMode
+                                ? i18n('Edit License Key Group')
+                                : i18n('Create New License Key Group')
+                        }`}</Modal.Title>
+                    </Modal.Header>
+                    <Modal.Body>
+                        {isDisplayModal && (
+                            <LicenseKeyGroupsEditor
+                                version={version}
+                                licenseModelId={licenseModelId}
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    </Modal.Body>
+                </Modal>
+            </div>
+        );
+    }
+
+    filterList() {
+        let { licenseKeyGroupsList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return licenseKeyGroupsList.filter(
+                ({
+                    name = '',
+                    description = '',
+                    operationalScope = '',
+                    type = ''
+                }) => {
+                    return (
+                        escape(name).match(filter) ||
+                        escape(description).match(filter) ||
+                        escape(this.extractValue(operationalScope)).match(
+                            filter
+                        ) ||
+                        escape(type).match(filter)
+                    );
+                }
+            );
+        } else {
+            return licenseKeyGroupsList;
+        }
+    }
+
+    renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode) {
+        let { id, name, description, operationalScope, type } = licenseKeyGroup;
+        let {
+            onEditLicenseKeyGroupClick,
+            onDeleteLicenseKeyGroupClick
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                onSelect={() => onEditLicenseKeyGroupClick(licenseKeyGroup)}
+                onDelete={() => onDeleteLicenseKeyGroupClick(licenseKeyGroup)}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div className="text name">{name}</div>
+                </div>
+
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Operational Scope')}</div>
+                    <div className="text operational-scope">
+                        {operationalScope &&
+                            this.getOperationalScopes(operationalScope)}
+                    </div>
+
+                    <div className="title">{i18n('Type')}</div>
+                    <div className="text type">
+                        {InputOptions.getTitleByName(optionsInputValues, type)}
+                    </div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Description')}</div>
+                    <div className="text description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
+
+    getOperationalScopes(operationalScope) {
+        if (
+            operationalScope.choices &&
+            operationalScope.choices.toString() === i18n(optionInputOther.OTHER)
+        ) {
+            return operationalScope.other;
+        } else if (operationalScope.choices) {
+            let allOpScopes = '';
+            for (let opScope of operationalScope.choices) {
+                allOpScopes +=
+                    allOpScopes === ''
+                        ? InputOptions.getTitleByName(
+                              optionsInputValues,
+                              opScope
+                          )
+                        : `, ${InputOptions.getTitleByName(
+                              optionsInputValues,
+                              opScope
+                          )}`;
+            }
+            return allOpScopes;
+        } else {
+            return '';
+        }
+    }
+
+    extractValue(item) {
+        if (item === undefined) {
+            return '';
+        } //TODO fix it sooner rather than later
+
+        return item
+            ? item.choice === optionInputOther.OTHER
+              ? item.other
+              : InputOptions.getTitleByName(optionsInputValues, item.choice)
+            : '';
+    }
 }
 
 export default LicenseKeyGroupsListEditorView;
 
 export function generateConfirmationMsg(licenseKeyGroupToDelete) {
-       let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : '';
-       let msg = i18n('Are you sure you want to delete "{name}"?', {name: name});
-       let subMsg = licenseKeyGroupToDelete.referencingFeatureGroups
-       && licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ?
-               i18n('This license key group is associated with one or more feature groups') :
-               '';
-       return (
-               <div>
-                       <p>{msg}</p>
-                       <p>{subMsg}</p>
-               </div>
-       );
+    let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : '';
+    let msg = i18n('Are you sure you want to delete "{name}"?', { name: name });
+    let subMsg =
+        licenseKeyGroupToDelete.referencingFeatureGroups &&
+        licenseKeyGroupToDelete.referencingFeatureGroups.length > 0
+            ? i18n(
+                  'This license key group is associated with one or more feature groups'
+              )
+            : '';
+    return (
+        <div>
+            <p>{msg}</p>
+            <p>{subMsg}</p>
+        </div>
+    );
 }
index 1f0a64e..1cd1da0 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './LicenseKeyGroupsConstants.js';
+import { actionTypes } from './LicenseKeyGroupsConstants.js';
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.LICENSE_KEY_GROUPS_LIST_LOADED:
-                       return [...action.response.results];
-               case actionTypes.DELETE_LICENSE_KEY_GROUP:
-                       return state.filter(licenseKeyGroup => licenseKeyGroup.id !== action.licenseKeyGroupId);
-               case actionTypes.ADD_LICENSE_KEY_GROUP:
-                       return [...state, action.licenseKeyGroup];
-               case actionTypes.EDIT_LICENSE_KEY_GROUP:
-                       const indexForEdit = state.findIndex(licenseKeyGroup => licenseKeyGroup.id === action.licenseKeyGroup.id);
-                       return [...state.slice(0, indexForEdit), action.licenseKeyGroup, ...state.slice(indexForEdit + 1)];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.LICENSE_KEY_GROUPS_LIST_LOADED:
+            return [...action.response.results];
+        case actionTypes.DELETE_LICENSE_KEY_GROUP:
+            return state.filter(
+                licenseKeyGroup =>
+                    licenseKeyGroup.id !== action.licenseKeyGroupId
+            );
+        case actionTypes.ADD_LICENSE_KEY_GROUP:
+            return [...state, action.licenseKeyGroup];
+        case actionTypes.EDIT_LICENSE_KEY_GROUP:
+            const indexForEdit = state.findIndex(
+                licenseKeyGroup =>
+                    licenseKeyGroup.id === action.licenseKeyGroup.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.licenseKeyGroup,
+                ...state.slice(indexForEdit + 1)
+            ];
+        default:
+            return state;
+    }
 };
-
index d483383..76ea36d 100644 (file)
@@ -1,25 +1,30 @@
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import LimitEditor from './LimitEditor.jsx';
 
-const mapStateToProps = ({licenseModel: {limitEditor}}) => {
+const mapStateToProps = ({ licenseModel: { limitEditor } }) => {
+    let { data, genericFieldInfo, formReady } = limitEditor;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let {data, genericFieldInfo, formReady} = limitEditor;  
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-
-       return {
-               data,           
-               genericFieldInfo,
-               isFormValid,
-               formReady
-       };
+    return {
+        data,
+        genericFieldInfo,
+        isFormValid,
+        formReady
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LimitEditor);
\ No newline at end of file
+export default connect(mapStateToProps, mapActionsToProps)(LimitEditor);
index 54f057e..0d1d4ea 100644 (file)
@@ -5,206 +5,349 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {LIMITS_FORM_NAME, selectValues} from './LimitEditorConstants.js';
+import { LIMITS_FORM_NAME, selectValues } from './LimitEditorConstants.js';
 import Button from 'sdc-ui/lib/react/Button.js';
 import Validator from 'nfvo-utils/Validator.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 
 const LimitPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       metric: PropTypes.shape({
-               choice: PropTypes.string,
-               other: PropTypes.string
-       }),
-       value: PropTypes.string,
-       aggregationFunction: PropTypes.string,
-       time: PropTypes.string,
-       unit: PropTypes.shape({
-               choice: PropTypes.string,
-               other: PropTypes.string
-       })
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    metric: PropTypes.shape({
+        choice: PropTypes.string,
+        other: PropTypes.string
+    }),
+    value: PropTypes.string,
+    aggregationFunction: PropTypes.string,
+    time: PropTypes.string,
+    unit: PropTypes.shape({
+        choice: PropTypes.string,
+        other: PropTypes.string
+    })
 });
 
 class LimitEditor extends React.Component {
-       static propTypes = {
-               data: LimitPropType,
-               limitsNames: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               isFormValid: PropTypes.bool,
-               formReady: PropTypes.bool,
-               genericFieldInfo: PropTypes.object.isRequired,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onValidateForm: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
+    static propTypes = {
+        data: LimitPropType,
+        limitsNames: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        isFormValid: PropTypes.bool,
+        formReady: PropTypes.bool,
+        genericFieldInfo: PropTypes.object.isRequired,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onValidateForm: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       componentDidUpdate(prevProps) {
-               if (this.props.formReady && this.props.formReady !== prevProps.formReady) {
-                       this.submit();
-               }
-       }
+    componentDidUpdate(prevProps) {
+        if (
+            this.props.formReady &&
+            this.props.formReady !== prevProps.formReady
+        ) {
+            this.submit();
+        }
+    }
 
-       render() {
-               let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo, onCancel, isFormValid, formReady, onValidateForm} = this.props;
-               let {name, description, metric, value, aggregationFunction, time, unit} = data;
-               return (
-                       <div className='limit-editor'>
-                       {!data.id &&
-                       <div className='limit-editor-title'>
-                               {data.name ? data.name : i18n('NEW LIMIT')}
-                       </div>}
-                       {
-                               genericFieldInfo &&
-                               <Form
-                                       ref='validationForm'
-                                       hasButtons={false}
-                                       isValid={isFormValid}
-                                       formReady={formReady}
-                                       onValidateForm={() => onValidateForm(LIMITS_FORM_NAME) }
-                                       labledButtons={false}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       className='limit-editor-form'>
-                                       <GridSection className='limit-editor-form-grid-section' hasLastColSet>
-                                               <GridItem colSpan={2}>
-                                                       <Input
-                                                               onChange={name => onDataChanged({name}, LIMITS_FORM_NAME, {name: () => this.validateName(name)})}
-                                                               label={i18n('Name')}
-                                                               data-test-id='limit-editor-name'
-                                                               value={name}
-                                                               isValid={genericFieldInfo.name.isValid}
-                                                               errorText={genericFieldInfo.name.errorText}
-                                                               isRequired={true}
-                                                               type='text'/>
-                                               </GridItem>
-                                               <GridItem colSpan={2} lastColInRow>
-                                                       <Input
-                                                               onChange={description => onDataChanged({description}, LIMITS_FORM_NAME)}
-                                                               label={i18n('Description')}
-                                                               data-test-id='limit-editor-description'
-                                                               value={description}
-                                                               isValid={genericFieldInfo.description.isValid}
-                                                               errorText={genericFieldInfo.description.errorText}
-                                                               isRequired={false}
-                                                               type='text'/>
-                                               </GridItem>
-                                               <GridItem colSpan={2}>
-                                                       <InputOptions
-                                                               onInputChange={()=>{}}
-                                                               isMultiSelect={false}
-                                                               isRequired={true}
-                                                               onEnumChange={metric => onDataChanged({metric:{choice: metric, other: ''}},
-                                                                       LIMITS_FORM_NAME)}
-                                                               onOtherChange={metric => onDataChanged({metric:{choice: optionInputOther.OTHER,
-                                                                       other: metric}}, LIMITS_FORM_NAME)}
-                                                               label={i18n('Metric')}
-                                                               data-test-id='limit-editor-metric'
-                                                               type='select'
-                                                               required={true}
-                                                               selectedEnum={metric && metric.choice}
-                                                               otherValue={metric && metric.other}
-                                                               values={selectValues.METRIC}
-                                                               isValid={genericFieldInfo.metric.isValid}
-                                                               errorText={genericFieldInfo.metric.errorText} />
-                                               </GridItem>
-                                               <GridItem>
-                                                       <Input
-                                                               onChange={value => onDataChanged({value}, LIMITS_FORM_NAME)}
-                                                               label={i18n('Metric value')}
-                                                               data-test-id='limit-editor-metric-value'
-                                                               value={value}
-                                                               isValid={genericFieldInfo.value.isValid}
-                                                               errorText={genericFieldInfo.value.errorText}
-                                                               isRequired={true}
-                                                               type='text'/>
-                                               </GridItem>
-                                               <GridItem lastColInRow>
-                                                       <InputOptions
-                                                               onInputChange={()=>{}}
-                                                               isMultiSelect={false}
-                                                               isRequired={false}
-                                                               onEnumChange={unit => onDataChanged({unit:{choice: unit, other: ''}},
-                                                                       LIMITS_FORM_NAME)}
-                                                               onOtherChange={unit => onDataChanged({unit:{choice: optionInputOther.OTHER,
-                                                                       other: unit}}, LIMITS_FORM_NAME)}
-                                                               label={i18n('Units')}
-                                                               data-test-id='limit-editor-units'
-                                                               type='select'
-                                                               required={false}
-                                                               selectedEnum={unit && unit.choice}
-                                                               otherValue={unit && unit.other}
-                                                               values={selectValues.UNIT}
-                                                               isValid={genericFieldInfo.unit.isValid}
-                                                               errorText={genericFieldInfo.unit.errorText} />
-                                               </GridItem>
-                                               <GridItem colSpan={2}>
-                                                       <Input
-                                                               onChange={e => {
-                                                                       const selectedIndex = e.target.selectedIndex;
-                                                                       const val = e.target.options[selectedIndex].value;
-                                                                       onDataChanged({aggregationFunction: val}, LIMITS_FORM_NAME);}
-                                                               }
-                                                               value={aggregationFunction}
-                                                               label={i18n('Aggregation Function')}
-                                                               data-test-id='limit-editor-aggregation-function'
-                                                               isValid={genericFieldInfo.aggregationFunction.isValid}
-                                                               errorText={genericFieldInfo.aggregationFunction.errorText}
-                                                               groupClassName='bootstrap-input-options'
-                                                               className='input-options-select'
-                                                               type='select' >
-                                                               {selectValues.AGGREGATION_FUNCTION.map(mtype =>
-                                                                       <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                                                       </Input>
-                                               </GridItem>
-                                               <GridItem>
-                                                       <Input
-                                                               onChange={e => {
-                                                                       const selectedIndex = e.target.selectedIndex;
-                                                                       const val = e.target.options[selectedIndex].value;
-                                                                       onDataChanged({time: val}, LIMITS_FORM_NAME);}
-                                                               }
-                                                               value={time}
-                                                               label={i18n('Time')}
-                                                               data-test-id='limit-editor-time'
-                                                               isValid={genericFieldInfo.time.isValid}
-                                                               errorText={genericFieldInfo.time.errorText}
-                                                               groupClassName='bootstrap-input-options'
-                                                               className='input-options-select'
-                                                               type='select' >
-                                                               {selectValues.TIME.map(mtype =>
-                                                                       <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                                                       </Input>
-                                               </GridItem>
-                                       </GridSection>
-                                       <GridSection className='limit-editor-buttons'>
-                                               <Button btnType='outline' disabled={!isFormValid || isReadOnlyMode} onClick={() => this.submit()} type='reset'>{i18n('Save')}</Button>
-                                               <Button btnType='outline' color='gray' onClick={onCancel} type='reset'>{i18n('Cancel')}</Button>
-                                       </GridSection>
-                               </Form>
-                       }
-                       </div>
-               );
-       }
+    render() {
+        let {
+            data = {},
+            onDataChanged,
+            isReadOnlyMode,
+            genericFieldInfo,
+            onCancel,
+            isFormValid,
+            formReady,
+            onValidateForm
+        } = this.props;
+        let {
+            name,
+            description,
+            metric,
+            value,
+            aggregationFunction,
+            time,
+            unit
+        } = data;
+        return (
+            <div className="limit-editor">
+                {!data.id && (
+                    <div className="limit-editor-title">
+                        {data.name ? data.name : i18n('NEW LIMIT')}
+                    </div>
+                )}
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={false}
+                        isValid={isFormValid}
+                        formReady={formReady}
+                        onValidateForm={() => onValidateForm(LIMITS_FORM_NAME)}
+                        labledButtons={false}
+                        isReadOnlyMode={isReadOnlyMode}
+                        className="limit-editor-form">
+                        <GridSection
+                            className="limit-editor-form-grid-section"
+                            hasLastColSet>
+                            <GridItem colSpan={2}>
+                                <Input
+                                    onChange={name =>
+                                        onDataChanged(
+                                            { name },
+                                            LIMITS_FORM_NAME,
+                                            {
+                                                name: () =>
+                                                    this.validateName(name)
+                                            }
+                                        )
+                                    }
+                                    label={i18n('Name')}
+                                    data-test-id="limit-editor-name"
+                                    value={name}
+                                    isValid={genericFieldInfo.name.isValid}
+                                    errorText={genericFieldInfo.name.errorText}
+                                    isRequired={true}
+                                    type="text"
+                                />
+                            </GridItem>
+                            <GridItem colSpan={2} lastColInRow>
+                                <Input
+                                    onChange={description =>
+                                        onDataChanged(
+                                            { description },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    label={i18n('Description')}
+                                    data-test-id="limit-editor-description"
+                                    value={description}
+                                    isValid={
+                                        genericFieldInfo.description.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.description.errorText
+                                    }
+                                    isRequired={false}
+                                    type="text"
+                                />
+                            </GridItem>
+                            <GridItem colSpan={2}>
+                                <InputOptions
+                                    onInputChange={() => {}}
+                                    isMultiSelect={false}
+                                    isRequired={true}
+                                    onEnumChange={metric =>
+                                        onDataChanged(
+                                            {
+                                                metric: {
+                                                    choice: metric,
+                                                    other: ''
+                                                }
+                                            },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    onOtherChange={metric =>
+                                        onDataChanged(
+                                            {
+                                                metric: {
+                                                    choice:
+                                                        optionInputOther.OTHER,
+                                                    other: metric
+                                                }
+                                            },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    label={i18n('Metric')}
+                                    data-test-id="limit-editor-metric"
+                                    type="select"
+                                    required={true}
+                                    selectedEnum={metric && metric.choice}
+                                    otherValue={metric && metric.other}
+                                    values={selectValues.METRIC}
+                                    isValid={genericFieldInfo.metric.isValid}
+                                    errorText={
+                                        genericFieldInfo.metric.errorText
+                                    }
+                                />
+                            </GridItem>
+                            <GridItem>
+                                <Input
+                                    onChange={value =>
+                                        onDataChanged(
+                                            { value },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    label={i18n('Metric value')}
+                                    data-test-id="limit-editor-metric-value"
+                                    value={value}
+                                    isValid={genericFieldInfo.value.isValid}
+                                    errorText={genericFieldInfo.value.errorText}
+                                    isRequired={true}
+                                    type="text"
+                                />
+                            </GridItem>
+                            <GridItem lastColInRow>
+                                <InputOptions
+                                    onInputChange={() => {}}
+                                    isMultiSelect={false}
+                                    isRequired={false}
+                                    onEnumChange={unit =>
+                                        onDataChanged(
+                                            {
+                                                unit: {
+                                                    choice: unit,
+                                                    other: ''
+                                                }
+                                            },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    onOtherChange={unit =>
+                                        onDataChanged(
+                                            {
+                                                unit: {
+                                                    choice:
+                                                        optionInputOther.OTHER,
+                                                    other: unit
+                                                }
+                                            },
+                                            LIMITS_FORM_NAME
+                                        )
+                                    }
+                                    label={i18n('Units')}
+                                    data-test-id="limit-editor-units"
+                                    type="select"
+                                    required={false}
+                                    selectedEnum={unit && unit.choice}
+                                    otherValue={unit && unit.other}
+                                    values={selectValues.UNIT}
+                                    isValid={genericFieldInfo.unit.isValid}
+                                    errorText={genericFieldInfo.unit.errorText}
+                                />
+                            </GridItem>
+                            <GridItem colSpan={2}>
+                                <Input
+                                    onChange={e => {
+                                        const selectedIndex =
+                                            e.target.selectedIndex;
+                                        const val =
+                                            e.target.options[selectedIndex]
+                                                .value;
+                                        onDataChanged(
+                                            { aggregationFunction: val },
+                                            LIMITS_FORM_NAME
+                                        );
+                                    }}
+                                    value={aggregationFunction}
+                                    label={i18n('Aggregation Function')}
+                                    data-test-id="limit-editor-aggregation-function"
+                                    isValid={
+                                        genericFieldInfo.aggregationFunction
+                                            .isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.aggregationFunction
+                                            .errorText
+                                    }
+                                    groupClassName="bootstrap-input-options"
+                                    className="input-options-select"
+                                    type="select">
+                                    {selectValues.AGGREGATION_FUNCTION.map(
+                                        mtype => (
+                                            <option
+                                                key={mtype.enum}
+                                                value={mtype.enum}>{`${
+                                                mtype.title
+                                            }`}</option>
+                                        )
+                                    )}
+                                </Input>
+                            </GridItem>
+                            <GridItem>
+                                <Input
+                                    onChange={e => {
+                                        const selectedIndex =
+                                            e.target.selectedIndex;
+                                        const val =
+                                            e.target.options[selectedIndex]
+                                                .value;
+                                        onDataChanged(
+                                            { time: val },
+                                            LIMITS_FORM_NAME
+                                        );
+                                    }}
+                                    value={time}
+                                    label={i18n('Time')}
+                                    data-test-id="limit-editor-time"
+                                    isValid={genericFieldInfo.time.isValid}
+                                    errorText={genericFieldInfo.time.errorText}
+                                    groupClassName="bootstrap-input-options"
+                                    className="input-options-select"
+                                    type="select">
+                                    {selectValues.TIME.map(mtype => (
+                                        <option
+                                            key={mtype.enum}
+                                            value={mtype.enum}>{`${
+                                            mtype.title
+                                        }`}</option>
+                                    ))}
+                                </Input>
+                            </GridItem>
+                        </GridSection>
+                        <GridSection className="limit-editor-buttons">
+                            <Button
+                                btnType="outline"
+                                disabled={!isFormValid || isReadOnlyMode}
+                                onClick={() => this.submit()}
+                                type="reset">
+                                {i18n('Save')}
+                            </Button>
+                            <Button
+                                btnType="outline"
+                                color="gray"
+                                onClick={onCancel}
+                                type="reset">
+                                {i18n('Cancel')}
+                            </Button>
+                        </GridSection>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       validateName(value) {
-               const {data: {id}, limitsNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: limitsNames});
+    validateName(value) {
+        const { data: { id }, limitsNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: limitsNames
+        });
 
-               return !isExists ?  {isValid: true, errorText: ''} :
-               {isValid: false, errorText: i18n('Limit by the name \'' + value + '\' already exists. Limit name must be unique')};
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "Limit by the name '" +
+                          value +
+                          "' already exists. Limit name must be unique"
+                  )
+              };
+    }
 
-
-       submit() {
-               if (!this.props.formReady) {
-                       this.props.onValidateForm(LIMITS_FORM_NAME);
-               } else {
-                       this.props.onSubmit();
-               }
-       }
+    submit() {
+        if (!this.props.formReady) {
+            this.props.onValidateForm(LIMITS_FORM_NAME);
+        } else {
+            this.props.onSubmit();
+        }
+    }
 }
 
 export default LimitEditor;
index 8ac845a..a275808 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes, selectValues} from './LimitEditorConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
-
+import { actionTypes, selectValues } from './LimitEditorConstants.js';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
 const LimitEditorActionHelper = {
-       openLimitsEditor(dispatch, {limit}) {
-               let modifiedLimit = {...limit};
-               if (limit && limit.metric) {
-                       modifiedLimit.metric = LimitEditorActionHelper.createChoiceObject(modifiedLimit.metric, selectValues.METRIC);
-               }
-               if (limit && limit.unit) {
-                       modifiedLimit.unit = LimitEditorActionHelper.createChoiceObject(modifiedLimit.unit, selectValues.UNIT);
-               }
-               dispatch({type: actionTypes.OPEN, limitItem: modifiedLimit});
-       },
+    openLimitsEditor(dispatch, { limit }) {
+        let modifiedLimit = { ...limit };
+        if (limit && limit.metric) {
+            modifiedLimit.metric = LimitEditorActionHelper.createChoiceObject(
+                modifiedLimit.metric,
+                selectValues.METRIC
+            );
+        }
+        if (limit && limit.unit) {
+            modifiedLimit.unit = LimitEditorActionHelper.createChoiceObject(
+                modifiedLimit.unit,
+                selectValues.UNIT
+            );
+        }
+        dispatch({ type: actionTypes.OPEN, limitItem: modifiedLimit });
+    },
 
-       closeLimitsEditor(dispatch) {
-               dispatch({type: actionTypes.CLOSE});
-       },
+    closeLimitsEditor(dispatch) {
+        dispatch({ type: actionTypes.CLOSE });
+    },
 
-       createChoiceObject(value, optionsList) {
-               let option = optionsList.find(function(item) { return item.enum === value; });
-               if (!option) {
-                       return {
-                               choice: optionInputOther.OTHER,
-                               other: value
-                       };
-               }
-               else {
-                       return {
-                               choice: value,
-                               other: ''
-                       };
-               }
-       }
+    createChoiceObject(value, optionsList) {
+        let option = optionsList.find(function(item) {
+            return item.enum === value;
+        });
+        if (!option) {
+            return {
+                choice: optionInputOther.OTHER,
+                other: value
+            };
+        } else {
+            return {
+                choice: value,
+                other: ''
+            };
+        }
+    }
 };
 
 export default LimitEditorActionHelper;
index 9829e69..a916b95 100644 (file)
@@ -3,62 +3,61 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 // import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
 
 export const actionTypes = keyMirror({
-       OPEN: null,
-       CLOSE: null,
-       DATA_CHANGED: null,
+    OPEN: null,
+    CLOSE: null,
+    DATA_CHANGED: null
 });
 
 export const LIMITS_FORM_NAME = 'LIMITSFORM';
 
 export const selectValues = {
-       METRIC: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'BWTH', title: 'BWTH'},
-               {enum: 'Country', title: 'Country'},
-               {enum: 'Session', title: 'Session'},
-               {enum: 'LoB', title: 'LoB'},
-               {enum: 'Site', title: 'Site'},
-               {enum: 'Usage', title: 'Usage'}
-       ],
-       UNIT: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'trunk', title: 'Trunks'},
-               {enum: 'user', title: 'Users'},
-               {enum: 'subscriber', title: 'Subscribers'},
-               {enum: 'session', title: 'Sessions'},
-               {enum: 'tenant', title: 'Tenants'},
-               {enum: 'token', title: 'Tokens'},
-               {enum: 'seats', title: 'Seats'},
-               {enum: 'TB', title: 'TB'},
-               {enum: 'GB', title: 'GB'},
-               {enum: 'MB', title: 'MB'}
-       ],
-       AGGREGATION_FUNCTION: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Peak', title: 'Peak'},
-               {enum: 'Average', title: 'Average'}
-       ],
-       TIME: [
-               {enum: '', title: i18n('please select…')},
-               {enum: 'Day', title: 'Day'},
-               {enum: 'Month', title: 'Month'},
-               {enum: 'Hour', title: 'Hour'},
-               {enum: 'Minute', title: 'Minute'},
-               {enum: 'Second', title: 'Second'},
-               {enum: 'Milli-Second', title: 'Milli-Second'}
-       ]
-
+    METRIC: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'BWTH', title: 'BWTH' },
+        { enum: 'Country', title: 'Country' },
+        { enum: 'Session', title: 'Session' },
+        { enum: 'LoB', title: 'LoB' },
+        { enum: 'Site', title: 'Site' },
+        { enum: 'Usage', title: 'Usage' }
+    ],
+    UNIT: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'trunk', title: 'Trunks' },
+        { enum: 'user', title: 'Users' },
+        { enum: 'subscriber', title: 'Subscribers' },
+        { enum: 'session', title: 'Sessions' },
+        { enum: 'tenant', title: 'Tenants' },
+        { enum: 'token', title: 'Tokens' },
+        { enum: 'seats', title: 'Seats' },
+        { enum: 'TB', title: 'TB' },
+        { enum: 'GB', title: 'GB' },
+        { enum: 'MB', title: 'MB' }
+    ],
+    AGGREGATION_FUNCTION: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Peak', title: 'Peak' },
+        { enum: 'Average', title: 'Average' }
+    ],
+    TIME: [
+        { enum: '', title: i18n('please select…') },
+        { enum: 'Day', title: 'Day' },
+        { enum: 'Month', title: 'Month' },
+        { enum: 'Hour', title: 'Hour' },
+        { enum: 'Minute', title: 'Minute' },
+        { enum: 'Second', title: 'Second' },
+        { enum: 'Milli-Second', title: 'Milli-Second' }
+    ]
 };
 
 export const limitType = {
-       SERVICE_PROVIDER: 'ServiceProvider',
-       VENDOR: 'Vendor'
+    SERVICE_PROVIDER: 'ServiceProvider',
+    VENDOR: 'Vendor'
 };
 
 export const defaultState = {
-       LIMITS_EDITOR_DATA: {
-               metric: {choice: '', other: ''},
-       }
+    LIMITS_EDITOR_DATA: {
+        metric: { choice: '', other: '' }
+    }
 };
 
 export const NEW_LIMIT_TEMP_ID = 'NEW_LIMIT_TEMP_ID';
index 99d94a0..a0c3b0b 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes, LIMITS_FORM_NAME, defaultState} from './LimitEditorConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import {
+    actionTypes,
+    LIMITS_FORM_NAME,
+    defaultState
+} from './LimitEditorConstants.js';
+import { other as optionInputOther } from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.OPEN:
-                       return {
-                               ...state,
-                               data: action.limitItem ? {...action.limitItem} : defaultState.LIMITS_EDITOR_DATA,
-                               formReady: null,
-                               formName: LIMITS_FORM_NAME,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
-                                       },
-                                       'metric' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}]
-                                       },
-                                       'value' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       'unit' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'aggregationFunction' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'time' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               }
-                       };
-               case actionTypes.CLOSE:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.OPEN:
+            return {
+                ...state,
+                data: action.limitItem
+                    ? { ...action.limitItem }
+                    : defaultState.LIMITS_EDITOR_DATA,
+                formReady: null,
+                formName: LIMITS_FORM_NAME,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ]
+                    },
+                    metric: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            {
+                                type: 'requiredChoiceWithOther',
+                                data: optionInputOther.OTHER
+                            }
+                        ]
+                    },
+                    value: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    unit: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    aggregationFunction: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    time: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                }
+            };
+        case actionTypes.CLOSE:
+            return {};
+        default:
+            return state;
+    }
 };
index 4841d03..2667560 100644 (file)
@@ -18,99 +18,157 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import LimitEditor from './LimitEditor.js';
-import {NEW_LIMIT_TEMP_ID, selectValues} from './LimitEditorConstants.js';
+import { NEW_LIMIT_TEMP_ID, selectValues } from './LimitEditorConstants.js';
 
-const LimitItem = ({isReadOnlyMode, limit, onDelete, onSelect}) => {
-       const {name, description, value, metric, aggregationFunction = '', time = ''} = limit;
-       const timeLabel = time ? `per ${time}` : '';
-       let metricOption = selectValues.METRIC.find(item => item.enum === metric);
-       metricOption = metricOption ? metricOption.title : metric;
+const LimitItem = ({ isReadOnlyMode, limit, onDelete, onSelect }) => {
+    const {
+        name,
+        description,
+        value,
+        metric,
+        aggregationFunction = '',
+        time = ''
+    } = limit;
+    const timeLabel = time ? `per ${time}` : '';
+    let metricOption = selectValues.METRIC.find(item => item.enum === metric);
+    metricOption = metricOption ? metricOption.title : metric;
 
-       return (
-               <ListEditorItemView
-                       onDelete={onDelete}
-                       onSelect={onSelect}
-                       isReadOnlyMode={isReadOnlyMode}>
-                       <div className='list-editor-item-view-field limit-name'>
-                               <div className='text name'>{name}</div>
-                       </div>
+    return (
+        <ListEditorItemView
+            onDelete={onDelete}
+            onSelect={onSelect}
+            isReadOnlyMode={isReadOnlyMode}>
+            <div className="list-editor-item-view-field limit-name">
+                <div className="text name">{name}</div>
+            </div>
 
-                       <div className='list-editor-item-view-field limit-description'>
-                               <div className='text description'>{description}</div>
-                       </div>
+            <div className="list-editor-item-view-field limit-description">
+                <div className="text description">{description}</div>
+            </div>
 
-                       <div className='list-editor-item-view-field limit-metric-details'>
-                               <div className='text description'>{`${metricOption} ${value} ${aggregationFunction} ${timeLabel}`}</div>
-                       </div>
-               </ListEditorItemView>
-       );
+            <div className="list-editor-item-view-field limit-metric-details">
+                <div className="text description">{`${metricOption} ${value} ${aggregationFunction} ${timeLabel}`}</div>
+            </div>
+        </ListEditorItemView>
+    );
 };
 
 class Limits extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
+    render() {
+        const {
+            isReadOnlyMode = false,
+            limitEditor,
+            limitsList = [],
+            onCloseLimitEditor,
+            selectedLimit
+        } = this.props;
+        let limitsNames = {};
+        for (let i = 0; i < limitsList.length; i++) {
+            limitsNames[limitsList[i].name.toLowerCase()] = limitsList[i].id;
+        }
+        return (
+            <div className="license-model-limits-view">
+                <ListEditorView isReadOnlyMode={isReadOnlyMode}>
+                    {this.props.selectedLimit === NEW_LIMIT_TEMP_ID &&
+                        limitEditor.data && (
+                            <LimitEditor
+                                limitsNames={limitsNames}
+                                onCancel={onCloseLimitEditor}
+                                onSubmit={() => this.submit()}
+                                isReadOnlyMode={isReadOnlyMode}
+                            />
+                        )}
+                    {limitsList.length === 0 &&
+                        !limitEditor.data && (
+                            <div className="no-limits-text">
+                                {i18n('There are no limits')}
+                            </div>
+                        )}
+                    {limitsList.map(limit => (
+                        <div key={limit.id} className="limit-item-wrapper">
+                            <LimitItem
+                                onDelete={() => this.deleteLimit(limit)}
+                                onSelect={
+                                    selectedLimit
+                                        ? undefined
+                                        : () => this.props.onSelectLimit(limit)
+                                }
+                                clickable={!selectedLimit}
+                                isReadOnlyMode={isReadOnlyMode}
+                                limit={limit}
+                            />
+                            {limit.id === selectedLimit &&
+                                limitEditor.data && (
+                                    <LimitEditor
+                                        limitsNames={limitsNames}
+                                        onCancel={onCloseLimitEditor}
+                                        onSubmit={() => this.submit()}
+                                        isReadOnlyMode={isReadOnlyMode}
+                                    />
+                                )}
+                        </div>
+                    ))}
+                </ListEditorView>
+            </div>
+        );
+    }
 
-       state = {
-               localFilter: ''
-       };
+    submit() {
+        let {
+            onSubmit,
+            onCloseLimitEditor,
+            parent,
+            limitEditor,
+            licenseModelId,
+            version,
+            limitType
+        } = this.props;
+        onSubmit(
+            { type: limitType, ...limitEditor.data },
+            parent,
+            licenseModelId,
+            version
+        ).then(() => onCloseLimitEditor());
+    }
 
-       render() {
-               const {isReadOnlyMode = false, limitEditor, limitsList = [], onCloseLimitEditor, selectedLimit} = this.props;
-               let limitsNames = {};
-               for (let i = 0; i < limitsList.length; i++) {
-                       limitsNames[limitsList[i].name.toLowerCase()] = limitsList[i].id;
-               }
-               return (
-                       <div className='license-model-limits-view'>
-                               <ListEditorView isReadOnlyMode={isReadOnlyMode}>
-                                       {this.props.selectedLimit === NEW_LIMIT_TEMP_ID && limitEditor.data &&
-                                               <LimitEditor limitsNames={limitsNames} onCancel={onCloseLimitEditor} onSubmit={ () => this.submit()} isReadOnlyMode={isReadOnlyMode}/>
-                                       }
-                                       {limitsList.length === 0 && !limitEditor.data && <div className='no-limits-text'>{i18n('There are no limits')}</div>}
-                                       {limitsList.map(limit =>
-                                       <div key={limit.id}  className='limit-item-wrapper'>
-                                               <LimitItem
-                                                       onDelete={() => this.deleteLimit(limit)}
-                                                       onSelect={selectedLimit ? undefined : () => this.props.onSelectLimit(limit)}
-                                                       clickable={!selectedLimit}
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       limit={limit}/>
-                                               {limit.id === selectedLimit &&  limitEditor.data &&
-                                                       <LimitEditor
-                                                               limitsNames={limitsNames}
-                                                               onCancel={onCloseLimitEditor}
-                                                               onSubmit={ () => this.submit()}
-                                                               isReadOnlyMode={isReadOnlyMode} />
-                                               }
-                                       </div> )}
-                               </ListEditorView>
+    deleteLimit(limit) {
+        let {
+            onDelete,
+            parent,
+            licenseModelId,
+            version,
+            onCloseLimitEditor,
+            selectedLimit
+        } = this.props;
+        onDelete({
+            limit,
+            parent,
+            licenseModelId,
+            version,
+            onCloseLimitEditor,
+            selectedLimit
+        });
+    }
 
-                       </div>
-               );
-       }
-
-       submit() {
-               let {onSubmit, onCloseLimitEditor, parent, limitEditor, licenseModelId, version, limitType} = this.props;
-               onSubmit({type: limitType, ...limitEditor.data}, parent, licenseModelId, version).then(() => onCloseLimitEditor());
-       }
-
-       deleteLimit(limit) {
-               let {onDelete, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit} = this.props;
-               onDelete({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit});
-       }
-
-       filterList() {
-               let {limitsList = []} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return limitsList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return limitsList;
-               }
-       }
+    filterList() {
+        let { limitsList = [] } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return limitsList.filter(({ name = '', description = '' }) => {
+                return (
+                    escape(name).match(filter) ||
+                    escape(description).match(filter)
+                );
+            });
+        } else {
+            return limitsList;
+        }
+    }
 }
 
 export default Limits;
index 1b8ecb9..679f997 100644 (file)
 
 // items/{itemId}/users
 
-let list = [
-       
-];
+let list = [];
 
 export default {
-       fetch() {
-               return Promise.resolve({
-                       listCount: list.length,
-                       results: list
-               });
-       },
+    fetch() {
+        return Promise.resolve({
+            listCount: list.length,
+            results: list
+        });
+    },
 
-       put(url, payload) {
-               // let {removedUsers, addedUsers} = payload;
-               // users = users.filter(user => !removedUsers.map(user => user.userId).includes(user.userId)).concat(addedUsers);
-               payload.id = Math.random() * (1000 - 1) + 1;
-               list.push(payload);
-               return Promise.resolve();
-       },
+    put(url, payload) {
+        // let {removedUsers, addedUsers} = payload;
+        // users = users.filter(user => !removedUsers.map(user => user.userId).includes(user.userId)).concat(addedUsers);
+        payload.id = Math.random() * (1000 - 1) + 1;
+        list.push(payload);
+        return Promise.resolve();
+    },
 
-       destroy(url) {
-               const parts = url.split('/');
-               const id = parts[parts.length - 1];
-               let newList  = list.filter(item => item.id !== id);
-               list = newList;
-               return Promise.resolve();
-       }
-};
\ No newline at end of file
+    destroy(url) {
+        const parts = url.split('/');
+        const id = parts[parts.length - 1];
+        let newList = list.filter(item => item.id !== id);
+        list = newList;
+        return Promise.resolve();
+    }
+};
index 54941aa..2b10e42 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
 import LicenseModelOverviewView from './LicenseModelOverviewView.jsx';
-import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js';
+import {
+    overviewEditorHeaders,
+    selectedButton
+} from './LicenseModelOverviewConstants.js';
 import licenseModelOverviewActionHelper from './licenseModelOverviewActionHelper.js';
 
 export const mapStateToProps = ({
-       licenseModel: {
-               licenseModelEditor,
-               entitlementPool,
-               licenseAgreement,
-               featureGroup,
-               licenseKeyGroup,
-               licenseModelOverview
-       }
+    licenseModel: {
+        licenseModelEditor,
+        entitlementPool,
+        licenseAgreement,
+        featureGroup,
+        licenseKeyGroup,
+        licenseModelOverview
+    }
 }) => {
-
-       let modalHeader, licensingDataList;
-       let isDisplayModal = false;
-
-       const reduceLicenseKeyGroups = (accum, licenseKeyGroupId) => {
-               let curLicenseKeyGroup = licenseKeyGroup.licenseKeyGroupsList.find(item => {return item.id === licenseKeyGroupId;});
-               if (curLicenseKeyGroup) {
-                       accum.push({
-                               ...curLicenseKeyGroup,
-                               itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
-                       });
-               }
-               return accum;
-       };
-
-       const reduceEntitlementPools = (accum, entitlementPoolId) => {
-               let curEntitlementPool = entitlementPool.entitlementPoolsList.find(item => {return item.id === entitlementPoolId;});
-               if (curEntitlementPool) {
-                       accum.push ({
-                               ...curEntitlementPool,
-                               itemType: overviewEditorHeaders.ENTITLEMENT_POOL
-                       });
-               }
-               return accum;
-       };
-
-       const reduceFeatureGroups = (accum, featureGroupId) => {
-               let curFeatureGroup = featureGroup.featureGroupsList.find(item => {return item.id === featureGroupId;});
-               if (curFeatureGroup) {
-                       let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = curFeatureGroup;
-                       accum.push({
-                               ...curFeatureGroup,
-                               itemType: overviewEditorHeaders.FEATURE_GROUP,
-                               children: [
-                                       ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [],
-                                       ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : []
-                               ]
-                       });
-               }
-               return accum;
-       };
-
-
-       const checkEP  = (accum, elem) => {
-               if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) {
-                       accum.push({
-                               ...elem,
-                               itemType: overviewEditorHeaders.ENTITLEMENT_POOL
-                       });
-               }
-               return accum;
-       };
-
-       const checkLG = (accum, elem) => {
-               if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) {
-                       accum.push({
-                               ...elem,
-                               itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
-                       });
-               }
-               return accum;
-       };
-
-       const checkFG = (accum, elem) => {
-               if (!elem.referencingLicenseAgreements || !elem.referencingLicenseAgreements.length) {
-                       let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = elem;
-                       accum.push({
-                               ...elem,
-                               itemType: overviewEditorHeaders.FEATURE_GROUP,
-
-                               children: [
-                                       ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [],
-                                       ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : []
-                               ]
-
-                       });
-               }
-               return accum;
-       };
-
-
-
-       const mapLicenseAgreementData = licenseAgreement => {
-               let {featureGroupsIds = []} = licenseAgreement;
-               return {
-                       ...licenseAgreement,
-                       itemType: overviewEditorHeaders.LICENSE_AGREEMENT,
-                       children: featureGroupsIds.length ? featureGroupsIds.reduce(reduceFeatureGroups, []) : []
-               };
-       };
-
-       if (entitlementPool.entitlementPoolEditor && entitlementPool.entitlementPoolEditor.data) {
-               modalHeader = overviewEditorHeaders.ENTITLEMENT_POOL;
-               isDisplayModal = true;
-       }else
-       if (licenseAgreement.licenseAgreementEditor && licenseAgreement.licenseAgreementEditor.data) {
-               modalHeader = overviewEditorHeaders.LICENSE_AGREEMENT;
-               isDisplayModal = true;
-       }else
-       if (featureGroup.featureGroupEditor && featureGroup.featureGroupEditor.data) {
-               modalHeader = overviewEditorHeaders.FEATURE_GROUP;
-               isDisplayModal = true;
-       }else
-       if (licenseKeyGroup.licenseKeyGroupsEditor && licenseKeyGroup.licenseKeyGroupsEditor.data) {
-               modalHeader = overviewEditorHeaders.LICENSE_KEY_GROUP;
-               isDisplayModal = true;
-       }
-
-       let orphanDataList = [
-               ...featureGroup.featureGroupsList.reduce(checkFG, []),
-               ...entitlementPool.entitlementPoolsList.reduce(checkEP, []),
-               ...licenseKeyGroup.licenseKeyGroupsList.reduce(checkLG, [])
-       ];
-
-       licensingDataList = licenseAgreement.licenseAgreementList && licenseAgreement.licenseAgreementList.length ? licenseAgreement.licenseAgreementList.map(mapLicenseAgreementData) : [];
-       let selectedTab = licenseModelOverview.selectedTab;
-       // on first entry, we will decide what tab to open depending on data. if there are no connections, we will open the orphans
-       if (selectedTab === null) {
-               selectedTab = (licensingDataList.length) ? selectedButton.VLM_LIST_VIEW : selectedButton.NOT_IN_USE;
-       }
-
-       return {
-               isDisplayModal,
-               modalHeader,
-               licenseModelId: licenseModelEditor.data.id,
-               version: licenseModelEditor.data.version,
-               licensingDataList,
-               orphanDataList,
-               selectedTab
-       };
+    let modalHeader, licensingDataList;
+    let isDisplayModal = false;
+
+    const reduceLicenseKeyGroups = (accum, licenseKeyGroupId) => {
+        let curLicenseKeyGroup = licenseKeyGroup.licenseKeyGroupsList.find(
+            item => {
+                return item.id === licenseKeyGroupId;
+            }
+        );
+        if (curLicenseKeyGroup) {
+            accum.push({
+                ...curLicenseKeyGroup,
+                itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
+            });
+        }
+        return accum;
+    };
+
+    const reduceEntitlementPools = (accum, entitlementPoolId) => {
+        let curEntitlementPool = entitlementPool.entitlementPoolsList.find(
+            item => {
+                return item.id === entitlementPoolId;
+            }
+        );
+        if (curEntitlementPool) {
+            accum.push({
+                ...curEntitlementPool,
+                itemType: overviewEditorHeaders.ENTITLEMENT_POOL
+            });
+        }
+        return accum;
+    };
+
+    const reduceFeatureGroups = (accum, featureGroupId) => {
+        let curFeatureGroup = featureGroup.featureGroupsList.find(item => {
+            return item.id === featureGroupId;
+        });
+        if (curFeatureGroup) {
+            let {
+                entitlementPoolsIds = [],
+                licenseKeyGroupsIds = []
+            } = curFeatureGroup;
+            accum.push({
+                ...curFeatureGroup,
+                itemType: overviewEditorHeaders.FEATURE_GROUP,
+                children: [
+                    ...(entitlementPoolsIds.length
+                        ? entitlementPoolsIds.reduce(reduceEntitlementPools, [])
+                        : []),
+                    ...(licenseKeyGroupsIds.length
+                        ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, [])
+                        : [])
+                ]
+            });
+        }
+        return accum;
+    };
+
+    const checkEP = (accum, elem) => {
+        if (
+            !elem.referencingFeatureGroups ||
+            !elem.referencingFeatureGroups.length
+        ) {
+            accum.push({
+                ...elem,
+                itemType: overviewEditorHeaders.ENTITLEMENT_POOL
+            });
+        }
+        return accum;
+    };
+
+    const checkLG = (accum, elem) => {
+        if (
+            !elem.referencingFeatureGroups ||
+            !elem.referencingFeatureGroups.length
+        ) {
+            accum.push({
+                ...elem,
+                itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
+            });
+        }
+        return accum;
+    };
+
+    const checkFG = (accum, elem) => {
+        if (
+            !elem.referencingLicenseAgreements ||
+            !elem.referencingLicenseAgreements.length
+        ) {
+            let { entitlementPoolsIds = [], licenseKeyGroupsIds = [] } = elem;
+            accum.push({
+                ...elem,
+                itemType: overviewEditorHeaders.FEATURE_GROUP,
+
+                children: [
+                    ...(entitlementPoolsIds.length
+                        ? entitlementPoolsIds.reduce(reduceEntitlementPools, [])
+                        : []),
+                    ...(licenseKeyGroupsIds.length
+                        ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, [])
+                        : [])
+                ]
+            });
+        }
+        return accum;
+    };
+
+    const mapLicenseAgreementData = licenseAgreement => {
+        let { featureGroupsIds = [] } = licenseAgreement;
+        return {
+            ...licenseAgreement,
+            itemType: overviewEditorHeaders.LICENSE_AGREEMENT,
+            children: featureGroupsIds.length
+                ? featureGroupsIds.reduce(reduceFeatureGroups, [])
+                : []
+        };
+    };
+
+    if (
+        entitlementPool.entitlementPoolEditor &&
+        entitlementPool.entitlementPoolEditor.data
+    ) {
+        modalHeader = overviewEditorHeaders.ENTITLEMENT_POOL;
+        isDisplayModal = true;
+    } else if (
+        licenseAgreement.licenseAgreementEditor &&
+        licenseAgreement.licenseAgreementEditor.data
+    ) {
+        modalHeader = overviewEditorHeaders.LICENSE_AGREEMENT;
+        isDisplayModal = true;
+    } else if (
+        featureGroup.featureGroupEditor &&
+        featureGroup.featureGroupEditor.data
+    ) {
+        modalHeader = overviewEditorHeaders.FEATURE_GROUP;
+        isDisplayModal = true;
+    } else if (
+        licenseKeyGroup.licenseKeyGroupsEditor &&
+        licenseKeyGroup.licenseKeyGroupsEditor.data
+    ) {
+        modalHeader = overviewEditorHeaders.LICENSE_KEY_GROUP;
+        isDisplayModal = true;
+    }
+
+    let orphanDataList = [
+        ...featureGroup.featureGroupsList.reduce(checkFG, []),
+        ...entitlementPool.entitlementPoolsList.reduce(checkEP, []),
+        ...licenseKeyGroup.licenseKeyGroupsList.reduce(checkLG, [])
+    ];
+
+    licensingDataList =
+        licenseAgreement.licenseAgreementList &&
+        licenseAgreement.licenseAgreementList.length
+            ? licenseAgreement.licenseAgreementList.map(mapLicenseAgreementData)
+            : [];
+    let selectedTab = licenseModelOverview.selectedTab;
+    // on first entry, we will decide what tab to open depending on data. if there are no connections, we will open the orphans
+    if (selectedTab === null) {
+        selectedTab = licensingDataList.length
+            ? selectedButton.VLM_LIST_VIEW
+            : selectedButton.NOT_IN_USE;
+    }
+
+    return {
+        isDisplayModal,
+        modalHeader,
+        licenseModelId: licenseModelEditor.data.id,
+        version: licenseModelEditor.data.version,
+        licensingDataList,
+        orphanDataList,
+        selectedTab
+    };
 };
 
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
-       return {
-               onCallVCAction: action => {
-                       LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action});
-               },
-               onTabSelect: (buttonTab) => licenseModelOverviewActionHelper.selectVLMListView(dispatch,{buttonTab})
-       };
+const mapActionsToProps = (dispatch, { licenseModelId }) => {
+    return {
+        onCallVCAction: action => {
+            LicenseModelActionHelper.performVCAction(dispatch, {
+                licenseModelId,
+                action
+            });
+        },
+        onTabSelect: buttonTab =>
+            licenseModelOverviewActionHelper.selectVLMListView(dispatch, {
+                buttonTab
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(LicenseModelOverviewView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    LicenseModelOverviewView
+);
index 56b2338..b05da58 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const overviewItems = keyMirror({
-       LICENSE_AGREEMENTS: 'License Agreements',
-       FEATURE_GROUPS: 'Feature Groups',
-       ENTITLEMENT_POOLS: 'Entitlement Pools',
-       LICENSE_KEY_GROUPS: 'License Key Groups'
+    LICENSE_AGREEMENTS: 'License Agreements',
+    FEATURE_GROUPS: 'Feature Groups',
+    ENTITLEMENT_POOLS: 'Entitlement Pools',
+    LICENSE_KEY_GROUPS: 'License Key Groups'
 });
 
 export const overviewEditorHeaders = keyMirror({
-       LICENSE_AGREEMENT: 'License Agreement',
-       FEATURE_GROUP: 'Feature Group',
-       ENTITLEMENT_POOL: 'Entitlement Pool',
-       LICENSE_KEY_GROUP: 'License Key Group'
+    LICENSE_AGREEMENT: 'License Agreement',
+    FEATURE_GROUP: 'Feature Group',
+    ENTITLEMENT_POOL: 'Entitlement Pool',
+    LICENSE_KEY_GROUP: 'License Key Group'
 });
 
 export const actionTypes = keyMirror({
-       LICENSE_MODEL_OVERVIEW_TAB_SELECTED: null,
-       LM_DATA_CHANGED: null
+    LICENSE_MODEL_OVERVIEW_TAB_SELECTED: null,
+    LM_DATA_CHANGED: null
 });
 
 export const selectedButton = {
-       VLM_LIST_VIEW: 'VLM_LIST_VIEW',
-       NOT_IN_USE: 'NOT_IN_USE'
+    VLM_LIST_VIEW: 'VLM_LIST_VIEW',
+    NOT_IN_USE: 'NOT_IN_USE'
 };
 
 export const VLM_DESCRIPTION_FORM = 'VLMDEWSCRIPTIONFORM';
index 39109af..6899360 100644 (file)
@@ -23,87 +23,137 @@ import EntitlementPoolsEditor from '../entitlementPools/EntitlementPoolsEditor.j
 import FeatureGroupEditor from '../featureGroups/FeatureGroupEditor.js';
 import LicenseAgreementEditor from '../licenseAgreement/LicenseAgreementEditor.js';
 import LicenseKeyGroupsEditor from '../licenseKeyGroups/LicenseKeyGroupsEditor.js';
-import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js';
+import {
+    overviewEditorHeaders,
+    selectedButton
+} from './LicenseModelOverviewConstants.js';
 
 import SummaryView from './SummaryView.jsx';
 import VLMListView from './VLMListView.jsx';
 import ListButtons from './summary/ListButtons.jsx';
 
-
-const setModalClassName = (modalHeader) => {
-       switch (modalHeader) {
-               case overviewEditorHeaders.ENTITLEMENT_POOL:
-                       return 'entitlement-pools-modal';
-               case overviewEditorHeaders.LICENSE_AGREEMENT:
-                       return 'license-agreement-modal';
-               case overviewEditorHeaders.FEATURE_GROUP:
-                       return 'feature-group-modal';
-               case overviewEditorHeaders.LICENSE_KEY_GROUP:
-                       return 'license-key-groups-modal';
-               default:
-                       return '';
-       }
+const setModalClassName = modalHeader => {
+    switch (modalHeader) {
+        case overviewEditorHeaders.ENTITLEMENT_POOL:
+            return 'entitlement-pools-modal';
+        case overviewEditorHeaders.LICENSE_AGREEMENT:
+            return 'license-agreement-modal';
+        case overviewEditorHeaders.FEATURE_GROUP:
+            return 'feature-group-modal';
+        case overviewEditorHeaders.LICENSE_KEY_GROUP:
+            return 'license-key-groups-modal';
+        default:
+            return '';
+    }
 };
 
 class LicenseModelOverviewView extends React.Component {
+    static propTypes = {
+        isDisplayModal: PropTypes.bool,
+        isReadOnlyMode: PropTypes.bool,
+        licenseModelId: PropTypes.string,
+        licensingDataList: PropTypes.array,
+        orphanDataList: PropTypes.array,
+        modalHeader: PropTypes.string,
+        selectedTab: PropTypes.string,
+        onTabSelect: PropTypes.func,
+        onCallVCAction: PropTypes.func,
+        onClose: PropTypes.func
+    };
 
-       static propTypes = {
-               isDisplayModal: PropTypes.bool,
-               isReadOnlyMode: PropTypes.bool,
-               licenseModelId: PropTypes.string,
-               licensingDataList: PropTypes.array,
-               orphanDataList: PropTypes.array,
-               modalHeader: PropTypes.string,
-               selectedTab: PropTypes.string,
-               onTabSelect: PropTypes.func,
-               onCallVCAction: PropTypes.func,
-               onClose: PropTypes.func
-       };
-
-       render() {
-               let {isDisplayModal, modalHeader, licensingDataList, selectedTab, onTabSelect, orphanDataList, isReadOnlyMode} = this.props;
-               let selectedInUse = selectedTab !== selectedButton.NOT_IN_USE;
-               let dataList = selectedInUse ? licensingDataList : orphanDataList;
-               return(
-                       <div className='license-model-overview'>
-                               <SummaryView  isReadOnlyMode={isReadOnlyMode}/>
-                               <div className={classNames('overview-list-section ', !selectedInUse ? 'overview-list-orphans' : '' )}>
-                                       <div className='vlm-list-tab-panel'>
-                                               <ListButtons onTabSelect={onTabSelect}
-                                                        selectedTab={selectedTab}
-                                                        hasOrphans={orphanDataList.length > 0}
-                                                        hasLicensing={licensingDataList.length > 0}/>
-                                       </div>
-                                       <VLMListView licensingDataList={dataList} showInUse={selectedInUse}/>
-                               </div>
-                               {
-                                       isDisplayModal &&
-                                       <Modal show={isDisplayModal} bsSize='large' animation={true} className={classNames('onborading-modal license-model-modal', setModalClassName(modalHeader))}>
-                                               <Modal.Header>
-                                                       <Modal.Title>{`${i18n('Create New ')}${i18n(modalHeader)}`}</Modal.Title>
-                                               </Modal.Header>
-                                               <Modal.Body>
-                                                       {this.renderModalBody(modalHeader)}
-                                               </Modal.Body>
-                                       </Modal>
-                               }
-                       </div>
-               );
-       }
+    render() {
+        let {
+            isDisplayModal,
+            modalHeader,
+            licensingDataList,
+            selectedTab,
+            onTabSelect,
+            orphanDataList,
+            isReadOnlyMode
+        } = this.props;
+        let selectedInUse = selectedTab !== selectedButton.NOT_IN_USE;
+        let dataList = selectedInUse ? licensingDataList : orphanDataList;
+        return (
+            <div className="license-model-overview">
+                <SummaryView isReadOnlyMode={isReadOnlyMode} />
+                <div
+                    className={classNames(
+                        'overview-list-section ',
+                        !selectedInUse ? 'overview-list-orphans' : ''
+                    )}>
+                    <div className="vlm-list-tab-panel">
+                        <ListButtons
+                            onTabSelect={onTabSelect}
+                            selectedTab={selectedTab}
+                            hasOrphans={orphanDataList.length > 0}
+                            hasLicensing={licensingDataList.length > 0}
+                        />
+                    </div>
+                    <VLMListView
+                        licensingDataList={dataList}
+                        showInUse={selectedInUse}
+                    />
+                </div>
+                {isDisplayModal && (
+                    <Modal
+                        show={isDisplayModal}
+                        bsSize="large"
+                        animation={true}
+                        className={classNames(
+                            'onborading-modal license-model-modal',
+                            setModalClassName(modalHeader)
+                        )}>
+                        <Modal.Header>
+                            <Modal.Title>{`${i18n('Create New ')}${i18n(
+                                modalHeader
+                            )}`}</Modal.Title>
+                        </Modal.Header>
+                        <Modal.Body>
+                            {this.renderModalBody(modalHeader)}
+                        </Modal.Body>
+                    </Modal>
+                )}
+            </div>
+        );
+    }
 
-       renderModalBody(modalHeader) {
-               let {licenseModelId, version, isReadOnlyMode} = this.props;
-               switch (modalHeader) {
-                       case overviewEditorHeaders.ENTITLEMENT_POOL:
-                               return <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>;
-                       case overviewEditorHeaders.LICENSE_AGREEMENT:
-                               return <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>;
-                       case overviewEditorHeaders.FEATURE_GROUP:
-                               return <FeatureGroupEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>;
-                       case overviewEditorHeaders.LICENSE_KEY_GROUP:
-                               return <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>;
-               }
-       }
+    renderModalBody(modalHeader) {
+        let { licenseModelId, version, isReadOnlyMode } = this.props;
+        switch (modalHeader) {
+            case overviewEditorHeaders.ENTITLEMENT_POOL:
+                return (
+                    <EntitlementPoolsEditor
+                        version={version}
+                        licenseModelId={licenseModelId}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                );
+            case overviewEditorHeaders.LICENSE_AGREEMENT:
+                return (
+                    <LicenseAgreementEditor
+                        version={version}
+                        licenseModelId={licenseModelId}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                );
+            case overviewEditorHeaders.FEATURE_GROUP:
+                return (
+                    <FeatureGroupEditor
+                        version={version}
+                        licenseModelId={licenseModelId}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                );
+            case overviewEditorHeaders.LICENSE_KEY_GROUP:
+                return (
+                    <LicenseKeyGroupsEditor
+                        version={version}
+                        licenseModelId={licenseModelId}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                );
+        }
+    }
 }
 
-export default  LicenseModelOverviewView;
+export default LicenseModelOverviewView;
index 4053f14..f416b0a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {default as VendorDataView} from './summary/VendorDataView.js';
-import {default as SummaryCountList} from './summary/SummaryCountList.js';
+import { default as VendorDataView } from './summary/VendorDataView.js';
+import { default as SummaryCountList } from './summary/SummaryCountList.js';
 
 class SummaryView extends Component {
-       render() {
-               const {isReadOnlyMode} = this.props;
-               return(
-                       <div className='overview-top-section'>
-                               <div className='page-title'>{i18n('overview')}</div>
-                               <div className='license-model-overview-top'>
-                                       <VendorDataView isReadOnlyMode={isReadOnlyMode}/>
-                                       <SummaryCountList isReadOnlyMode={isReadOnlyMode}/>
-                               </div>
-                       </div>
-               );
-       }
+    render() {
+        const { isReadOnlyMode } = this.props;
+        return (
+            <div className="overview-top-section">
+                <div className="page-title">{i18n('overview')}</div>
+                <div className="license-model-overview-top">
+                    <VendorDataView isReadOnlyMode={isReadOnlyMode} />
+                    <SummaryCountList isReadOnlyMode={isReadOnlyMode} />
+                </div>
+            </div>
+        );
+    }
 }
 
 export default SummaryView;
index 012bd6e..d91960e 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import {Collapse} from 'react-bootstrap';
+import { Collapse } from 'react-bootstrap';
 import LicenseAgreement from './listItems/LicenseAgreement.jsx';
 import EntitlementPool from './listItems/EntitlementPool.jsx';
 import FeatureGroup from './listItems/FeatureGroup.jsx';
 import LicenseKeyGroup from './listItems/LicenseKeyGroup.jsx';
-import {overviewEditorHeaders} from './LicenseModelOverviewConstants.js';
+import { overviewEditorHeaders } from './LicenseModelOverviewConstants.js';
 
 class VLMListView extends Component {
+    static propTypes = {
+        licensingDataList: PropTypes.array,
+        showInUse: PropTypes.bool
+    };
 
-       static propTypes = {
-               licensingDataList: PropTypes.array,
-               showInUse: PropTypes.bool
-       };
+    state = {};
 
-       state = {
+    render() {
+        let { licensingDataList = [] } = this.props;
+        return (
+            <div className="vlm-list-view">
+                <div>
+                    <ul className="vlm-list" data-test-id="vlm-list">
+                        {licensingDataList.map(item =>
+                            this.renderLicensingItem(item)
+                        )}
+                    </ul>
+                </div>
+            </div>
+        );
+    }
 
-       };
+    renderLicensingItem(item) {
+        switch (item.itemType) {
+            case overviewEditorHeaders.LICENSE_AGREEMENT:
+                return this.renderLicenseAgreementItem(item);
+            case overviewEditorHeaders.FEATURE_GROUP:
+                return this.renderFeatureGroupItem(item);
+            case overviewEditorHeaders.LICENSE_KEY_GROUP:
+                return this.renderLicenseKeyGroupItem(item);
+            case overviewEditorHeaders.ENTITLEMENT_POOL:
+                return this.renderEntitlementPoolItem(item);
+            default:
+                return;
+        }
+    }
 
-       render() {
-               let {licensingDataList = []} = this.props;
-               return (
-                       <div className='vlm-list-view'>
-                               <div>
-                                       <ul className='vlm-list' data-test-id='vlm-list'>
-                                               {licensingDataList.map(item => this.renderLicensingItem(item))}
-                                       </ul>
-                               </div>
-                       </div>
-               );
-       }
+    renderLicenseAgreementItem(licenseAgreement) {
+        return (
+            <li key={licenseAgreement.id}>
+                <LicenseAgreement
+                    laData={licenseAgreement}
+                    isCollapsed={this.state[licenseAgreement.id]}
+                    onClick={event =>
+                        this.updateCollapsable(event, licenseAgreement.id)
+                    }
+                    isOrphan={!this.props.showInUse}
+                />
+                <Collapse in={this.state[licenseAgreement.id]}>
+                    <ul>
+                        {licenseAgreement.children &&
+                            licenseAgreement.children.map(item =>
+                                this.renderLicensingItem(item)
+                            )}
+                    </ul>
+                </Collapse>
+            </li>
+        );
+    }
 
-       renderLicensingItem(item) {
-               switch (item.itemType) {
-                       case overviewEditorHeaders.LICENSE_AGREEMENT :
-                               return this.renderLicenseAgreementItem(item);
-                       case overviewEditorHeaders.FEATURE_GROUP :
-                               return this.renderFeatureGroupItem(item);
-                       case overviewEditorHeaders.LICENSE_KEY_GROUP :
-                               return this.renderLicenseKeyGroupItem(item);
-                       case overviewEditorHeaders.ENTITLEMENT_POOL:
-                               return this.renderEntitlementPoolItem(item);
-                       default:
-                               return;
-               }
-       }
+    renderFeatureGroupItem(featureGroup) {
+        const { showInUse } = this.props;
+        return (
+            <li key={featureGroup.id}>
+                <FeatureGroup
+                    fgData={featureGroup}
+                    isCollapsed={this.state[featureGroup.id]}
+                    onClick={event =>
+                        this.updateCollapsable(event, featureGroup.id)
+                    }
+                    isOrphan={!this.props.showInUse}
+                />
+                {showInUse && (
+                    <Collapse in={this.state[featureGroup.id]}>
+                        <ul>
+                            {featureGroup.children &&
+                                featureGroup.children.map(item =>
+                                    this.renderLicensingItem(item)
+                                )}
+                        </ul>
+                    </Collapse>
+                )}
+            </li>
+        );
+    }
 
-       renderLicenseAgreementItem(licenseAgreement) {
-               return (
-                       <li  key={licenseAgreement.id}>
-                               <LicenseAgreement
-                                       laData={licenseAgreement}
-                                       isCollapsed={this.state[licenseAgreement.id]}
-                                       onClick={event => this.updateCollapsable(event, licenseAgreement.id) }
-                                       isOrphan={!this.props.showInUse}/>
-                               <Collapse in={this.state[licenseAgreement.id]}>
-                                       <ul>
-                                               {licenseAgreement.children && licenseAgreement.children.map(item => this.renderLicensingItem(item))}
-                                       </ul>
-                               </Collapse>
-                       </li>
-               );
-       }
+    renderEntitlementPoolItem(entitlementPool) {
+        return (
+            <li key={entitlementPool.id}>
+                <EntitlementPool
+                    epData={entitlementPool}
+                    isOrphan={!this.props.showInUse}
+                />
+            </li>
+        );
+    }
 
-       renderFeatureGroupItem(featureGroup) {
-               const {showInUse} = this.props;
-               return (
-                       <li key={featureGroup.id}>
-                               <FeatureGroup
-                                       fgData={featureGroup}
-                                       isCollapsed={this.state[featureGroup.id]}
-                                       onClick={event=> this.updateCollapsable(event, featureGroup.id) }
-                                       isOrphan={!this.props.showInUse}/>
-                               {
-                                       showInUse && <Collapse in={this.state[featureGroup.id]}>
-                                       <ul>
-                                               {featureGroup.children && featureGroup.children.map(item => this.renderLicensingItem(item))}
+    renderLicenseKeyGroupItem(licenseKeyGroup) {
+        return (
+            <li key={licenseKeyGroup.id}>
+                <LicenseKeyGroup
+                    lkgData={licenseKeyGroup}
+                    isOrphan={!this.props.showInUse}
+                />
+            </li>
+        );
+    }
 
-                                       </ul>
-                               </Collapse>
-                               }
-                       </li>
-               );
-       }
-
-       renderEntitlementPoolItem(entitlementPool) {
-               return (
-                       <li key={entitlementPool.id}>
-                               <EntitlementPool epData={entitlementPool} isOrphan={!this.props.showInUse}/>
-                       </li>
-               );
-       }
-
-       renderLicenseKeyGroupItem(licenseKeyGroup) {
-               return (
-                       <li key={licenseKeyGroup.id}>
-                               <LicenseKeyGroup lkgData={licenseKeyGroup} isOrphan={!this.props.showInUse}/>
-                       </li>
-               );
-       }
-
-       updateCollapsable(event, id) {
-               event.stopPropagation();
-               let obj = {};
-               obj[id] = !this.state[id];
-               this.setState(obj);
-       }
+    updateCollapsable(event, id) {
+        event.stopPropagation();
+        let obj = {};
+        obj[id] = !this.state[id];
+        this.setState(obj);
+    }
 }
 
 export default VLMListView;
index af9bc22..0e9fca7 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './LicenseModelOverviewConstants.js';
+import { actionTypes } from './LicenseModelOverviewConstants.js';
 
 export default {
-       selectVLMListView(dispatch, {buttonTab}) {
-               dispatch({
-                       type: actionTypes.LICENSE_MODEL_OVERVIEW_TAB_SELECTED,
-                       buttonTab
-               });
-       },
+    selectVLMListView(dispatch, { buttonTab }) {
+        dispatch({
+            type: actionTypes.LICENSE_MODEL_OVERVIEW_TAB_SELECTED,
+            buttonTab
+        });
+    },
 
-       editDescriptionOpen(dispatch, {description}) {
-               dispatch({
-                       type: actionTypes.LM_DATA_CHANGED,
-                       description
-               });
-       },
+    editDescriptionOpen(dispatch, { description }) {
+        dispatch({
+            type: actionTypes.LM_DATA_CHANGED,
+            description
+        });
+    },
 
-       editDescriptionClose(dispatch) {
-               dispatch({
-                       type: actionTypes.LM_DATA_CHANGED,
-                       description: undefined
-               });
-       }
+    editDescriptionClose(dispatch) {
+        dispatch({
+            type: actionTypes.LM_DATA_CHANGED,
+            description: undefined
+        });
+    }
 };
index 34d2ee6..60eba40 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {extractUnits} from '../../entitlementPools/EntitlementPoolsConstants.js';
+import { extractUnits } from '../../entitlementPools/EntitlementPoolsConstants.js';
 import ArrowCol from './listItemsComponents/ArrowCol.jsx';
 import ItemInfo from './listItemsComponents/ItemInfo.jsx';
 import IconCol from './listItemsComponents/IconCol.jsx';
-import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+import {
+    AdditionalDataCol,
+    AdditionalDataElement
+} from './listItemsComponents/AdditionalDataCol.jsx';
 
 class EntitlementPool extends Component {
-       render() {
-               let {epData: {name, description, thresholdValue, thresholdUnits}, isOrphan} = this.props;
-               return (
-                       <div className={`vlm-list-item vlm-list-item-ep ${isOrphan ? 'orphan-list-item' : ''}`} data-test-id='vlm-list-item-ep'>
-                               {!isOrphan && <ArrowCol/>}
-                               <IconCol className='ep-icon' text='EP'/>
-                               <ItemInfo name={name} description={description}/>
-                               <AdditionalDataCol>
-                                       {thresholdValue && <AdditionalDataElement
-                                               className='vlm-list-item-entitlement-metric'
-                                               name={i18n('Entitlement')}
-                                               value={`${thresholdValue} ${extractUnits(thresholdUnits)}`}/>
-                                       }
-                               </AdditionalDataCol>
-                       </div>
-               );
-       }
-
+    render() {
+        let {
+            epData: { name, description, thresholdValue, thresholdUnits },
+            isOrphan
+        } = this.props;
+        return (
+            <div
+                className={`vlm-list-item vlm-list-item-ep ${
+                    isOrphan ? 'orphan-list-item' : ''
+                }`}
+                data-test-id="vlm-list-item-ep">
+                {!isOrphan && <ArrowCol />}
+                <IconCol className="ep-icon" text="EP" />
+                <ItemInfo name={name} description={description} />
+                <AdditionalDataCol>
+                    {thresholdValue && (
+                        <AdditionalDataElement
+                            className="vlm-list-item-entitlement-metric"
+                            name={i18n('Entitlement')}
+                            value={`${thresholdValue} ${extractUnits(
+                                thresholdUnits
+                            )}`}
+                        />
+                    )}
+                </AdditionalDataCol>
+            </div>
+        );
+    }
 }
 
 export default EntitlementPool;
index 6d97dea..df1d813 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
-import {overviewEditorHeaders} from '../LicenseModelOverviewConstants.js';
+import React, { Component } from 'react';
+import { overviewEditorHeaders } from '../LicenseModelOverviewConstants.js';
 import ArrowCol from './listItemsComponents/ArrowCol.jsx';
 import ItemInfo from './listItemsComponents/ItemInfo.jsx';
 import IconCol from './listItemsComponents/IconCol.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+import {
+    AdditionalDataCol,
+    AdditionalDataElement
+} from './listItemsComponents/AdditionalDataCol.jsx';
 
 class FeatureGroup extends Component {
-       render() {
-               let {fgData: {name, manufacturerReferenceNumber, description, children = []}, isCollapsed, onClick, isOrphan} = this.props;
-               return (
-                       <div 
-                               onClick={e => onClick(e)} 
-                               className={`vlm-list-item vlm-list-item-fg ${isOrphan ? 'orphan-list-item' : ''} ${children.length && !isOrphan ? 'clickable' : ''}`} data-test-id='vlm-list-item-fg'>
-                               {!isOrphan && <ArrowCol isCollapsed={isCollapsed} length={children.length} />}
-                               <IconCol className='fg-icon' text='FG'/>
-                               <ItemInfo name={name} description={description}>
-                                       <div className='children-count'>
-                                               <span className='count-value'>
-                                                       {i18n('Entitlement Pools: ')}
-                                                       <span data-test-id='vlm-list-ep-count-value'>
-                                                               {`${children.filter(child => child.itemType === overviewEditorHeaders.ENTITLEMENT_POOL).length}`}
-                                                       </span>
-                                               </span>
-                                               <span className='fg-pipeline-separator'>|</span>
-                                               <span className='count-value'>
-                                                               {i18n('License Key Groups: ')}
-                                                               <span data-test-id='vlm-list-lkg-count-value'>
-                                                                       {`${children.filter(child => child.itemType === overviewEditorHeaders.LICENSE_KEY_GROUP).length}`}
-                                                               </span>
-                                               </span>
-                                       </div>
-                               </ItemInfo>
-                               <AdditionalDataCol>
-                                       <AdditionalDataElement
-                                               name={i18n('Manufacturer Reference Number')}
-                                               value={manufacturerReferenceNumber}
-                                               className='vlm-list-item-sku'/>
-                               </AdditionalDataCol>
-                       </div>
-               );
-       }
+    render() {
+        let {
+            fgData: {
+                name,
+                manufacturerReferenceNumber,
+                description,
+                children = []
+            },
+            isCollapsed,
+            onClick,
+            isOrphan
+        } = this.props;
+        return (
+            <div
+                onClick={e => onClick(e)}
+                className={`vlm-list-item vlm-list-item-fg ${
+                    isOrphan ? 'orphan-list-item' : ''
+                } ${children.length && !isOrphan ? 'clickable' : ''}`}
+                data-test-id="vlm-list-item-fg">
+                {!isOrphan && (
+                    <ArrowCol
+                        isCollapsed={isCollapsed}
+                        length={children.length}
+                    />
+                )}
+                <IconCol className="fg-icon" text="FG" />
+                <ItemInfo name={name} description={description}>
+                    <div className="children-count">
+                        <span className="count-value">
+                            {i18n('Entitlement Pools: ')}
+                            <span data-test-id="vlm-list-ep-count-value">
+                                {`${
+                                    children.filter(
+                                        child =>
+                                            child.itemType ===
+                                            overviewEditorHeaders.ENTITLEMENT_POOL
+                                    ).length
+                                }`}
+                            </span>
+                        </span>
+                        <span className="fg-pipeline-separator">|</span>
+                        <span className="count-value">
+                            {i18n('License Key Groups: ')}
+                            <span data-test-id="vlm-list-lkg-count-value">
+                                {`${
+                                    children.filter(
+                                        child =>
+                                            child.itemType ===
+                                            overviewEditorHeaders.LICENSE_KEY_GROUP
+                                    ).length
+                                }`}
+                            </span>
+                        </span>
+                    </div>
+                </ItemInfo>
+                <AdditionalDataCol>
+                    <AdditionalDataElement
+                        name={i18n('Manufacturer Reference Number')}
+                        value={manufacturerReferenceNumber}
+                        className="vlm-list-item-sku"
+                    />
+                </AdditionalDataCol>
+            </div>
+        );
+    }
 }
 
 export default FeatureGroup;
index dfbbe20..b409776 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
-import {optionsInputValues} from '../../licenseAgreement/LicenseAgreementConstants.js';
+import InputOptions, {
+    other as optionInputOther
+} from 'nfvo-components/input/validation/InputOptions.jsx';
+import { optionsInputValues } from '../../licenseAgreement/LicenseAgreementConstants.js';
 import ArrowCol from './listItemsComponents/ArrowCol.jsx';
 import ItemInfo from './listItemsComponents/ItemInfo.jsx';
 import IconCol from './listItemsComponents/IconCol.jsx';
-import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+import {
+    AdditionalDataCol,
+    AdditionalDataElement
+} from './listItemsComponents/AdditionalDataCol.jsx';
 
 class LicenseAgreement extends Component {
-       render() {
-               let {laData: {name, description, licenseTerm, children = []}, isCollapsed, onClick, isOrphan} = this.props;
-               return (
-                       <div 
-                               onClick={e => onClick(e)} 
-                               className={`vlm-list-item vlm-list-item-la ${isOrphan ? 'orphan-list-item' : ''} ${children.length && !isOrphan ? 'clickable' : ''} `} 
-                               data-test-id='vlm-list-la-item'>
-                               {!isOrphan && <ArrowCol isCollapsed={isCollapsed} length={children.length} />}
-                               <IconCol className='la-icon' text='LA'/>
-                               <ItemInfo name={name} description={description}>
-                                       <div className='children-count'>
-                                               <span className='count-value'>{i18n('Feature Groups: ')}<span data-test-id='vlm-list-fg-count-value'>{`${children.length}`}</span></span>
-                                       </div>
-                               </ItemInfo>
-                               <AdditionalDataCol>
-                                       <AdditionalDataElement
-                                               name={i18n('License Model Type')}
-                                               value={this.extractValue(licenseTerm)}/>
-                               </AdditionalDataCol>
-                       </div>
-               );
-       }
+    render() {
+        let {
+            laData: { name, description, licenseTerm, children = [] },
+            isCollapsed,
+            onClick,
+            isOrphan
+        } = this.props;
+        return (
+            <div
+                onClick={e => onClick(e)}
+                className={`vlm-list-item vlm-list-item-la ${
+                    isOrphan ? 'orphan-list-item' : ''
+                } ${children.length && !isOrphan ? 'clickable' : ''} `}
+                data-test-id="vlm-list-la-item">
+                {!isOrphan && (
+                    <ArrowCol
+                        isCollapsed={isCollapsed}
+                        length={children.length}
+                    />
+                )}
+                <IconCol className="la-icon" text="LA" />
+                <ItemInfo name={name} description={description}>
+                    <div className="children-count">
+                        <span className="count-value">
+                            {i18n('Feature Groups: ')}
+                            <span data-test-id="vlm-list-fg-count-value">{`${
+                                children.length
+                            }`}</span>
+                        </span>
+                    </div>
+                </ItemInfo>
+                <AdditionalDataCol>
+                    <AdditionalDataElement
+                        name={i18n('License Model Type')}
+                        value={this.extractValue(licenseTerm)}
+                    />
+                </AdditionalDataCol>
+            </div>
+        );
+    }
 
-       extractValue(item) {
-               if (item === undefined) {return '';} //TODO fix it later
+    extractValue(item) {
+        if (item === undefined) {
+            return '';
+        } //TODO fix it later
 
-               return  item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
-       }
+        return item
+            ? item.choice === optionInputOther.OTHER
+              ? item.other
+              : InputOptions.getTitleByName(optionsInputValues, item.choice)
+            : '';
+    }
 }
 
 export default LicenseAgreement;
index b1036aa..555acf8 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {extractValue, getOperationalScopes} from '../../licenseKeyGroups/LicenseKeyGroupsConstants.js';
+import {
+    extractValue,
+    getOperationalScopes
+} from '../../licenseKeyGroups/LicenseKeyGroupsConstants.js';
 import ArrowCol from './listItemsComponents/ArrowCol.jsx';
 import ItemInfo from './listItemsComponents/ItemInfo.jsx';
 import IconCol from './listItemsComponents/IconCol.jsx';
-import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+import {
+    AdditionalDataCol,
+    AdditionalDataElement
+} from './listItemsComponents/AdditionalDataCol.jsx';
 
 class LicenseKeyGroup extends Component {
-       render() {
-               let {lkgData: {name, description, operationalScope, type}, isOrphan} = this.props;
-               return (
-                       <div className={`vlm-list-item vlm-list-item-lkg ${isOrphan ? 'orphan-list-item' : ''}`} data-test-id='vlm-list-item-lkg'>
-                               {!isOrphan && <ArrowCol/>}
-                               <IconCol className='lkg-icon' text='LKG'/>
-                               <ItemInfo name={name} description={description}/>
-                               <AdditionalDataCol>
-                                       {operationalScope && operationalScope.choices && <AdditionalDataElement
-                                               className='vlm-list-item-operational-scope'
-                                               name={i18n('Operational Scope')}
-                                               value={getOperationalScopes(operationalScope)}/>}
-                                       <AdditionalDataElement
-                                               className='vlm-list-item-group-type'
-                                               name={i18n('Type')}
-                                               value={extractValue(type)}/>
-                               </AdditionalDataCol>
-                       </div>
-               );
-       }
-
+    render() {
+        let {
+            lkgData: { name, description, operationalScope, type },
+            isOrphan
+        } = this.props;
+        return (
+            <div
+                className={`vlm-list-item vlm-list-item-lkg ${
+                    isOrphan ? 'orphan-list-item' : ''
+                }`}
+                data-test-id="vlm-list-item-lkg">
+                {!isOrphan && <ArrowCol />}
+                <IconCol className="lkg-icon" text="LKG" />
+                <ItemInfo name={name} description={description} />
+                <AdditionalDataCol>
+                    {operationalScope &&
+                        operationalScope.choices && (
+                            <AdditionalDataElement
+                                className="vlm-list-item-operational-scope"
+                                name={i18n('Operational Scope')}
+                                value={getOperationalScopes(operationalScope)}
+                            />
+                        )}
+                    <AdditionalDataElement
+                        className="vlm-list-item-group-type"
+                        name={i18n('Type')}
+                        value={extractValue(type)}
+                    />
+                </AdditionalDataCol>
+            </div>
+        );
+    }
 }
 
 export default LicenseKeyGroup;
index ffc0991..0f9c783 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 
-function AdditionalDataCol({children}) {
-       return (
-               <div className='list-item-section list-item-additional-data-col'>
-                       <div className='additional-data-col-border'></div>
-                       <div className='additional-data'>
-                               {children}
-                       </div>
-               </div>
-       );
+function AdditionalDataCol({ children }) {
+    return (
+        <div className="list-item-section list-item-additional-data-col">
+            <div className="additional-data-col-border" />
+            <div className="additional-data">{children}</div>
+        </div>
+    );
 }
 
 AdditionalDataCol.propTypes = {
-       children: PropTypes.oneOfType([
-               PropTypes.arrayOf(PropTypes.node),
-               PropTypes.node
-       ])
+    children: PropTypes.oneOfType([
+        PropTypes.arrayOf(PropTypes.node),
+        PropTypes.node
+    ])
 };
 
-function AdditionalDataElement({className, name, value}) {
-       return (
-               <div className={className}>
-                       <span className='additional-data-name'>{name}: </span>
-                       <span className='additional-data-value'>{value}</span>
-               </div>
-       );
+function AdditionalDataElement({ className, name, value }) {
+    return (
+        <div className={className}>
+            <span className="additional-data-name">{name}: </span>
+            <span className="additional-data-value">{value}</span>
+        </div>
+    );
 }
 
 AdditionalDataElement.propTypes = {
-       name: PropTypes.string,
-       value: PropTypes.string,
-       className: PropTypes.string
+    name: PropTypes.string,
+    value: PropTypes.string,
+    className: PropTypes.string
 };
 
-export {AdditionalDataCol, AdditionalDataElement};
+export { AdditionalDataCol, AdditionalDataElement };
index 29aec64..de12eae 100644 (file)
@@ -17,20 +17,24 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
-function ArrowCol ({isCollapsed, length}) {
-       return (
-               <div className='list-item-section list-item-arrow-col'>
-                       <div className={classNames('arrow-icon', {'chevron': length > 0},
-                               {'down': (length > 0 && isCollapsed)},
-                               {'right': (length > 0 && (!isCollapsed))})} >
-                       </div>
-               </div>
-       );
+function ArrowCol({ isCollapsed, length }) {
+    return (
+        <div className="list-item-section list-item-arrow-col">
+            <div
+                className={classNames(
+                    'arrow-icon',
+                    { chevron: length > 0 },
+                    { down: length > 0 && isCollapsed },
+                    { right: length > 0 && !isCollapsed }
+                )}
+            />
+        </div>
+    );
 }
 
 ArrowCol.propTypes = {
-       isCollapsed: PropTypes.bool,
-       length: PropTypes.number
+    isCollapsed: PropTypes.bool,
+    length: PropTypes.number
 };
 
 export default ArrowCol;
index 826248e..61eeb03 100644 (file)
  */
 import React from 'react';
 
-function IconCol({className, text}) {
-       return (
-               <div className='list-item-section list-item-icon-col'>
-                       <div className={`overview-list-icon ${className ? className : ''}`}>{text}</div>
-               </div>
-       );
+function IconCol({ className, text }) {
+    return (
+        <div className="list-item-section list-item-icon-col">
+            <div className={`overview-list-icon ${className ? className : ''}`}>
+                {text}
+            </div>
+        </div>
+    );
 }
 
 export default IconCol;
index 95ae123..2d2cc8f 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 
-function ItemInfo({name, description, children}) {
-       return (
-               <div className='list-item-section vlm-item-info'>
-                       <div className='vlm-list-item-title'>
-                               <div className='item-name' data-test-id='vlm-list-item-name'>{name}</div>
-                               {children}
-                       </div>
-                       <div className='vlm-list-item-description'>{description}</div>
-               </div>
-       );
+function ItemInfo({ name, description, children }) {
+    return (
+        <div className="list-item-section vlm-item-info">
+            <div className="vlm-list-item-title">
+                <div className="item-name" data-test-id="vlm-list-item-name">
+                    {name}
+                </div>
+                {children}
+            </div>
+            <div className="vlm-list-item-description">{description}</div>
+        </div>
+    );
 }
 
 ItemInfo.propTypes = {
-       name: PropTypes.string,
-       description: PropTypes.string,
-       children: PropTypes.oneOfType([
-               PropTypes.arrayOf(PropTypes.node),
-               PropTypes.node
-       ])
+    name: PropTypes.string,
+    description: PropTypes.string,
+    children: PropTypes.oneOfType([
+        PropTypes.arrayOf(PropTypes.node),
+        PropTypes.node
+    ])
 };
 
 export default ItemInfo;
index af759f1..04a0017 100644 (file)
@@ -18,42 +18,54 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 
 class LicenseModelDescriptionEdit extends React.Component {
-       render() {
-               //TODO check if buttons
-               let {onDataChanged, description, genericFieldInfo} = this.props;
-               let {isValid, errorText} = genericFieldInfo.description;
-               let saveButtonClassName = isValid ? 'description-save' : 'description-save disabled';
-               return(
-                       <div className='vendor-description-edit'>
+    render() {
+        //TODO check if buttons
+        let { onDataChanged, description, genericFieldInfo } = this.props;
+        let { isValid, errorText } = genericFieldInfo.description;
+        let saveButtonClassName = isValid
+            ? 'description-save'
+            : 'description-save disabled';
+        return (
+            <div className="vendor-description-edit">
+                <Input
+                    onChange={description => onDataChanged({ description })}
+                    value={description}
+                    isValid={isValid}
+                    errorText={errorText}
+                    className="description-edit-textarea"
+                    type="textarea"
+                />
+                <div className="buttons-row">
+                    <div className="buttons-wrapper">
+                        <div
+                            onClick={() => this.submit()}
+                            className={saveButtonClassName}
+                            data-test-id="vlm-summary-vendor-desc-save-btn">
+                            {i18n('Save')}
+                        </div>
+                        <div
+                            onClick={() => this.onClose()}
+                            className="description-button"
+                            data-test-id="vlm-summary-vendor-desc-cancel-btn">
+                            {i18n('Cancel')}
+                        </div>
+                    </div>
+                </div>
+            </div>
+        );
+    }
 
-                               <Input
-                                       onChange={description => onDataChanged({description})}
-                                       value={description}
-                                       isValid={isValid}
-                                       errorText={errorText}
-                                       className='description-edit-textarea'
-                                       type='textarea'/>
-                               <div className='buttons-row'>
-                                       <div className='buttons-wrapper'>
-                                               <div onClick={() => this.submit()}  className={saveButtonClassName} data-test-id='vlm-summary-vendor-desc-save-btn'>{i18n('Save')}</div>
-                                               <div onClick={() => this.onClose()} className='description-button' data-test-id='vlm-summary-vendor-desc-cancel-btn'>{i18n('Cancel')}</div>
-                                       </div>
-                               </div>
-                       </div>
-               );
-       }
+    onClose() {
+        this.props.onClose();
+    }
 
-       onClose() {
-               this.props.onClose();
-       }
-
-       submit() {
-               let {onSubmit, data, description} = this.props;
-               onSubmit({
-                       ...data,
-                       description: description.trim()
-               });
-       }
+    submit() {
+        let { onSubmit, data, description } = this.props;
+        onSubmit({
+            ...data,
+            description: description.trim()
+        });
+    }
 }
 
 export default LicenseModelDescriptionEdit;
index 3fcac3c..d422d5d 100644 (file)
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import {selectedButton} from '../LicenseModelOverviewConstants.js';
+import { selectedButton } from '../LicenseModelOverviewConstants.js';
 import Tabs from 'sdc-ui/lib/react/Tabs.js';
 import Tab from 'sdc-ui/lib/react/Tab.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-function ListButtons ({onTabSelect, selectedTab, hasOrphans, hasLicensing}) {
-       // no data, no tabs
-       if (!hasLicensing && !hasOrphans) {
-               return null;
-       }
-       return (
-               <Tabs 
-                       onTabClick={(tabId) => onTabSelect(tabId)}
-                       activeTab={selectedTab}
-                       className='overview-buttons-section'
-                       type='header' >
-                       <Tab
-                               tabId={selectedButton.VLM_LIST_VIEW}
-                               title={i18n('Connections List')}
-                               data-test-id='vlm-overview-vlmlist-tab' />
-                       <Tab
-                               tabId={selectedButton.NOT_IN_USE}
-                               title={i18n('Orphans List')}
-                               data-test-id='vlm-overview-orphans-tab' />
-               </Tabs>
-       );
+function ListButtons({ onTabSelect, selectedTab, hasOrphans, hasLicensing }) {
+    // no data, no tabs
+    if (!hasLicensing && !hasOrphans) {
+        return null;
+    }
+    return (
+        <Tabs
+            onTabClick={tabId => onTabSelect(tabId)}
+            activeTab={selectedTab}
+            className="overview-buttons-section"
+            type="header">
+            <Tab
+                tabId={selectedButton.VLM_LIST_VIEW}
+                title={i18n('Connections List')}
+                data-test-id="vlm-overview-vlmlist-tab"
+            />
+            <Tab
+                tabId={selectedButton.NOT_IN_USE}
+                title={i18n('Orphans List')}
+                data-test-id="vlm-overview-orphans-tab"
+            />
+        </Tabs>
+    );
 }
 
 ListButtons.propTypes = {
-       onTabSelect: PropTypes.func,
-       selectedInUse: PropTypes.bool
+    onTabSelect: PropTypes.func,
+    selectedInUse: PropTypes.bool
 };
 
 export default ListButtons;
index 50c547e..144d9bc 100644 (file)
 import React from 'react';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 
-function  SummaryCountItem ({name, counter, onAdd, onNavigate, isReadOnlyMode}) {
-       //TODO check for buttons
-       return(
-               <div className='summary-count-item'>
-                       <div className='summary-name-and-count' onClick={onNavigate}>
-                               <span className='item-name' onClick={onNavigate}>{name}</span>
-                               <span className='item-count' onClick={onNavigate} data-test-id={'vlm-summary-vendor-counter-' + name.toLowerCase().replace(/\s/g,'-')}>({counter})</span>
-                       </div>
-                       <SVGIcon name='plusCircle' disabled={isReadOnlyMode} className={isReadOnlyMode ? 'disabled' : ''}
-                               color='secondary' onClick={onAdd} data-test-id={'vlm-summary-vendor-add-btn-' + name.toLowerCase().replace(/\s/g,'-')}/>
-               </div>
-       );
+function SummaryCountItem({
+    name,
+    counter,
+    onAdd,
+    onNavigate,
+    isReadOnlyMode
+}) {
+    //TODO check for buttons
+    return (
+        <div className="summary-count-item">
+            <div className="summary-name-and-count" onClick={onNavigate}>
+                <span className="item-name" onClick={onNavigate}>
+                    {name}
+                </span>
+                <span
+                    className="item-count"
+                    onClick={onNavigate}
+                    data-test-id={
+                        'vlm-summary-vendor-counter-' +
+                        name.toLowerCase().replace(/\s/g, '-')
+                    }>
+                    ({counter})
+                </span>
+            </div>
+            <SVGIcon
+                name="plusCircle"
+                disabled={isReadOnlyMode}
+                className={isReadOnlyMode ? 'disabled' : ''}
+                color="secondary"
+                onClick={onAdd}
+                data-test-id={
+                    'vlm-summary-vendor-add-btn-' +
+                    name.toLowerCase().replace(/\s/g, '-')
+                }
+            />
+        </div>
+    );
 }
 
 export default SummaryCountItem;
-
index 15b6649..711bb7a 100644 (file)
  * permissions and limitations under the License.
  */
 import React from 'react';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 import EntitlementPoolsActionHelper from '../../entitlementPools/EntitlementPoolsActionHelper.js';
 import LicenseAgreementActionHelper from '../../licenseAgreement/LicenseAgreementActionHelper.js';
 import LicenseKeyGroupsActionHelper from '../../licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
 import FeatureGroupsActionHelper from '../../featureGroups/FeatureGroupsActionHelper.js';
 
-import {overviewItems} from '../LicenseModelOverviewConstants.js';
+import { overviewItems } from '../LicenseModelOverviewConstants.js';
 import SummaryCountItem from './SummaryCountItem.jsx';
 
 export const mapStateToProps = ({
-       licenseModel: {
-               licenseModelEditor,
-               licenseAgreement: {licenseAgreementList},
-               featureGroup: {featureGroupsList},
-               entitlementPool: {entitlementPoolsList},
-               licenseKeyGroup: {licenseKeyGroupsList}
-       }
+    licenseModel: {
+        licenseModelEditor,
+        licenseAgreement: { licenseAgreementList },
+        featureGroup: { featureGroupsList },
+        entitlementPool: { entitlementPoolsList },
+        licenseKeyGroup: { licenseKeyGroupsList }
+    }
 }) => {
+    let { vendorName, description, id, version } = licenseModelEditor.data;
+    let counts = [
+        {
+            name: overviewItems.LICENSE_AGREEMENTS,
+            count: licenseAgreementList.length
+        },
+        { name: overviewItems.FEATURE_GROUPS, count: featureGroupsList.length },
+        {
+            name: overviewItems.ENTITLEMENT_POOLS,
+            count: entitlementPoolsList.length
+        },
+        {
+            name: overviewItems.LICENSE_KEY_GROUPS,
+            count: licenseKeyGroupsList.length
+        }
+    ];
 
-       let {vendorName, description, id, version} = licenseModelEditor.data;
-       let counts = [
-               {name: overviewItems.LICENSE_AGREEMENTS, count: licenseAgreementList.length},
-               {name: overviewItems.FEATURE_GROUPS, count: featureGroupsList.length},
-               {name: overviewItems.ENTITLEMENT_POOLS, count: entitlementPoolsList.length},
-               {name: overviewItems.LICENSE_KEY_GROUPS, count: licenseKeyGroupsList.length},
-       ];
-
-       return {
-               vendorName,
-               licenseModelId: id,
-               description,
-               counts,
-               version
-       };
-
+    return {
+        vendorName,
+        licenseModelId: id,
+        description,
+        counts,
+        version
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onEditorOpenClick: (name, licenseModelId, version) => {
-                       switch (name) {
-                               case overviewItems.ENTITLEMENT_POOLS:
-                                       EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch);
-                                       break;
-                               case overviewItems.FEATURE_GROUPS:
-                                       FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version});
-                                       break;
-                               case overviewItems.LICENSE_AGREEMENTS:
-                                       LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version});
-                                       break;
-                               case overviewItems.LICENSE_KEY_GROUPS:
-                                       LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch);
-                                       break;
-                               default:
-                                       break;
-                       }
-               },
-               onNavigateClick: ({name, licenseModelId, version}) => {
-                       let screenToNavigate;
-                       switch (name) {
-                               case overviewItems.ENTITLEMENT_POOLS:
-                                       screenToNavigate = enums.SCREEN.ENTITLEMENT_POOLS;
-                                       break;
-                               case overviewItems.FEATURE_GROUPS:
-                                       screenToNavigate = enums.SCREEN.FEATURE_GROUPS;
-                                       break;
-                               case overviewItems.LICENSE_AGREEMENTS:
-                                       screenToNavigate = enums.SCREEN.LICENSE_AGREEMENTS;
-                                       break;
-                               case overviewItems.LICENSE_KEY_GROUPS:
-                                       screenToNavigate = enums.SCREEN.LICENSE_KEY_GROUPS;
-                                       break;
-                               default:
-                                       break;
-                       }
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: screenToNavigate, screenType: screenTypes.LICENSE_MODEL,
-                               props: {licenseModelId, version}
-                       });
-               }
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onEditorOpenClick: (name, licenseModelId, version) => {
+            switch (name) {
+                case overviewItems.ENTITLEMENT_POOLS:
+                    EntitlementPoolsActionHelper.openEntitlementPoolsEditor(
+                        dispatch
+                    );
+                    break;
+                case overviewItems.FEATURE_GROUPS:
+                    FeatureGroupsActionHelper.openFeatureGroupsEditor(
+                        dispatch,
+                        {
+                            licenseModelId,
+                            version
+                        }
+                    );
+                    break;
+                case overviewItems.LICENSE_AGREEMENTS:
+                    LicenseAgreementActionHelper.openLicenseAgreementEditor(
+                        dispatch,
+                        {
+                            licenseModelId,
+                            version
+                        }
+                    );
+                    break;
+                case overviewItems.LICENSE_KEY_GROUPS:
+                    LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(
+                        dispatch
+                    );
+                    break;
+                default:
+                    break;
+            }
+        },
+        onNavigateClick: ({ name, licenseModelId, version }) => {
+            let screenToNavigate;
+            switch (name) {
+                case overviewItems.ENTITLEMENT_POOLS:
+                    screenToNavigate = enums.SCREEN.ENTITLEMENT_POOLS;
+                    break;
+                case overviewItems.FEATURE_GROUPS:
+                    screenToNavigate = enums.SCREEN.FEATURE_GROUPS;
+                    break;
+                case overviewItems.LICENSE_AGREEMENTS:
+                    screenToNavigate = enums.SCREEN.LICENSE_AGREEMENTS;
+                    break;
+                case overviewItems.LICENSE_KEY_GROUPS:
+                    screenToNavigate = enums.SCREEN.LICENSE_KEY_GROUPS;
+                    break;
+                default:
+                    break;
+            }
+            ScreensHelper.loadScreen(dispatch, {
+                screen: screenToNavigate,
+                screenType: screenTypes.LICENSE_MODEL,
+                props: { licenseModelId, version }
+            });
+        }
+    };
 };
 
 export class SummaryCountList extends React.Component {
+    render() {
+        let { counts } = this.props;
+        return (
+            <div className="summary-count-list">
+                {counts.map(item => this.renderItem(item))}
+            </div>
+        );
+    }
 
-       render() {
-               let {counts} = this.props;
-               return(
-                       <div className='summary-count-list'>
-                               {counts.map(item => this.renderItem(item))}
-                       </div>
-               );
-       }
-
-       renderItem(item){
-               const {name, count} = item;
-               const {isReadOnlyMode} = this.props;
-               return(
-                       <SummaryCountItem isReadOnlyMode={isReadOnlyMode} name={name} counter={count} onNavigate={() => this.onNavigate(name)} onAdd={() => this.onAdd(name)} key={name} />
-               );
-       }
+    renderItem(item) {
+        const { name, count } = item;
+        const { isReadOnlyMode } = this.props;
+        return (
+            <SummaryCountItem
+                isReadOnlyMode={isReadOnlyMode}
+                name={name}
+                counter={count}
+                onNavigate={() => this.onNavigate(name)}
+                onAdd={() => this.onAdd(name)}
+                key={name}
+            />
+        );
+    }
 
-       onAdd(name) {
-               let {onEditorOpenClick, licenseModelId, isReadOnlyMode, version} = this.props;
-               if (!isReadOnlyMode) {
-                       onEditorOpenClick(name, licenseModelId, version);
-               }
-       }
+    onAdd(name) {
+        let {
+            onEditorOpenClick,
+            licenseModelId,
+            isReadOnlyMode,
+            version
+        } = this.props;
+        if (!isReadOnlyMode) {
+            onEditorOpenClick(name, licenseModelId, version);
+        }
+    }
 
-       onNavigate(name) {
-               let {onNavigateClick, licenseModelId, version} = this.props;
-               onNavigateClick({licenseModelId, name, version});
-       }
+    onNavigate(name) {
+        let { onNavigateClick, licenseModelId, version } = this.props;
+        onNavigateClick({ licenseModelId, name, version });
+    }
 }
 
 export default connect(mapStateToProps, mapActionsToProps)(SummaryCountList);
index 616355d..62fc2c3 100644 (file)
@@ -13,8 +13,8 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
-import {connect} from 'react-redux';
+import React, { Component } from 'react';
+import { connect } from 'react-redux';
 
 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
@@ -23,89 +23,139 @@ import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import licenseModelOverviewActionHelper from '../licenseModelOverviewActionHelper.js';
 import LicenseModelActionHelper from '../../LicenseModelActionHelper.js';
 import LicenseModelDescriptionEdit from './LicenseModelDescriptionEdit.jsx';
-import {VLM_DESCRIPTION_FORM} from '../LicenseModelOverviewConstants.js';
+import { VLM_DESCRIPTION_FORM } from '../LicenseModelOverviewConstants.js';
 
 export const mapStateToProps = ({
-       licenseModel: {
-               licenseModelEditor: {data},
-               licenseModelOverview: {descriptionEditor: {data: descriptionData = {}, genericFieldInfo}}
-       }
+    licenseModel: {
+        licenseModelEditor: { data },
+        licenseModelOverview: {
+            descriptionEditor: { data: descriptionData = {}, genericFieldInfo }
+        }
+    }
 }) => {
-       let {description} = descriptionData;
-       return {
-               data,
-               description,
-               genericFieldInfo
-       };
+    let { description } = descriptionData;
+    return {
+        data,
+        description,
+        genericFieldInfo
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VLM_DESCRIPTION_FORM}),
-               onCancel: () => licenseModelOverviewActionHelper.editDescriptionClose(dispatch),
-               onSubmit: (licenseModel) => {
-                       licenseModelOverviewActionHelper.editDescriptionClose(dispatch);
-                       LicenseModelActionHelper.saveLicenseModel(dispatch, {licenseModel});
-               },
-               onVendorDescriptionEdit: description => licenseModelOverviewActionHelper.editDescriptionOpen(dispatch,{description})
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: VLM_DESCRIPTION_FORM
+            }),
+        onCancel: () =>
+            licenseModelOverviewActionHelper.editDescriptionClose(dispatch),
+        onSubmit: licenseModel => {
+            licenseModelOverviewActionHelper.editDescriptionClose(dispatch);
+            LicenseModelActionHelper.saveLicenseModel(dispatch, {
+                licenseModel
+            });
+        },
+        onVendorDescriptionEdit: description =>
+            licenseModelOverviewActionHelper.editDescriptionOpen(dispatch, {
+                description
+            })
+    };
 };
 
 export class VendorDataView extends Component {
-       render() {
-               let {data: {vendorName}, description, isReadOnlyMode} = this.props;
-               return (
-                       <div className='vendor-data-view'>
-                               <div className='vendor-title'>vendor</div>
-                               <div className='vendor-name' data-test-id='vlm-summary-vendor-name'>{vendorName}</div>
-                               {
-                                       description !== undefined && !isReadOnlyMode ? this.renderDescriptionEdit() : this.renderDescription()
-                               }
-                       </div>
-               );
-       }
+    render() {
+        let { data: { vendorName }, description, isReadOnlyMode } = this.props;
+        return (
+            <div className="vendor-data-view">
+                <div className="vendor-title">vendor</div>
+                <div
+                    className="vendor-name"
+                    data-test-id="vlm-summary-vendor-name">
+                    {vendorName}
+                </div>
+                {description !== undefined && !isReadOnlyMode
+                    ? this.renderDescriptionEdit()
+                    : this.renderDescription()}
+            </div>
+        );
+    }
 
-       componentWillUnmount() {
-               this.props.onCancel();
-       }
+    componentWillUnmount() {
+        this.props.onCancel();
+    }
 
+    renderDescription() {
+        let {
+            data: { description },
+            onVendorDescriptionEdit,
+            isReadOnlyMode
+        } = this.props;
+        return (
+            <div
+                onClick={() => {
+                    if (!isReadOnlyMode) {
+                        onVendorDescriptionEdit(description);
+                    }
+                }}
+                className={
+                    !isReadOnlyMode
+                        ? 'vendor-description'
+                        : 'vendor-description-readonly'
+                }>
+                {this.renderOverlay(
+                    <div
+                        className="description-data"
+                        data-test-id="vlm-summary-vendor-description">
+                        {description}
+                        {!isReadOnlyMode && <SVGIcon name="pencil" />}
+                    </div>
+                )}
+            </div>
+        );
+    }
 
-       renderDescription() {
-               let {data: {description}, onVendorDescriptionEdit, isReadOnlyMode} = this.props;
-               return (
-                       <div onClick={() => {if (!isReadOnlyMode) {onVendorDescriptionEdit(description);}}} className={!isReadOnlyMode ? 'vendor-description' : 'vendor-description-readonly'}>
-                               {this.renderOverlay(
-                                       <div className='description-data' data-test-id='vlm-summary-vendor-description'>
-                                               {description}
-                                               {!isReadOnlyMode && <SVGIcon name='pencil'/>}
-                                       </div>
-                               )}
-                       </div>
-               );
-       }
-
-       renderDescriptionEdit() {
-               let {onCancel, onDataChanged, onSubmit, description, genericFieldInfo, data} = this.props;
-               return(
-                       <LicenseModelDescriptionEdit onClose={onCancel} onDataChanged={onDataChanged} onSubmit={onSubmit} data={data} genericFieldInfo={genericFieldInfo} description={description}/>
-               );
-       }
-
-       renderOverlay(children) {
-               let {data: {description}, isReadOnlyMode} = this.props;
-               if (isReadOnlyMode) {
-                       return (
-                               <OverlayTrigger
-                                       placement='bottom'
-                                       overlay={<Tooltip className='vendor-description-tooltip' id='tooltip-bottom'>{description}</Tooltip>}
-                                       delayShow={400}>
-                                       {children}
-                               </OverlayTrigger>
-                       );
-               }
-               return children;
-       }
+    renderDescriptionEdit() {
+        let {
+            onCancel,
+            onDataChanged,
+            onSubmit,
+            description,
+            genericFieldInfo,
+            data
+        } = this.props;
+        return (
+            <LicenseModelDescriptionEdit
+                onClose={onCancel}
+                onDataChanged={onDataChanged}
+                onSubmit={onSubmit}
+                data={data}
+                genericFieldInfo={genericFieldInfo}
+                description={description}
+            />
+        );
+    }
 
+    renderOverlay(children) {
+        let { data: { description }, isReadOnlyMode } = this.props;
+        if (isReadOnlyMode) {
+            return (
+                <OverlayTrigger
+                    placement="bottom"
+                    overlay={
+                        <Tooltip
+                            className="vendor-description-tooltip"
+                            id="tooltip-bottom">
+                            {description}
+                        </Tooltip>
+                    }
+                    delayShow={400}>
+                    {children}
+                </OverlayTrigger>
+            );
+        }
+        return children;
+    }
 }
 
 export default connect(mapStateToProps, mapActionsToProps)(VendorDataView);
index 345c91e..7f361d2 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {catalogItemTypes, migrationStatusMapper} from './onboardingCatalog/OnboardingCatalogConstants.js';
-import {Tile, TileInfo, TileInfoLine, TileFooter, TileFooterCell} from 'sdc-ui/lib/react';
-import {TooltipWrapper} from './onboardingCatalog/Tooltip.jsx';
+import {
+    catalogItemTypes,
+    migrationStatusMapper
+} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import {
+    Tile,
+    TileInfo,
+    TileInfoLine,
+    TileFooter,
+    TileFooterCell
+} from 'sdc-ui/lib/react';
+import { TooltipWrapper } from './onboardingCatalog/Tooltip.jsx';
 
 const ITEM_TYPE_MAP = {
-       [catalogItemTypes.LICENSE_MODEL]: {
-               headerText: i18n('VLM'),
-               contentIconName: 'vlm',
-               color: 'purple'
-       },
-       [catalogItemTypes.SOFTWARE_PRODUCT]: {
-               headerText: i18n('VSP'),
-               contentIconName: 'vsp',
-               color: 'blue'
-       }
+    [catalogItemTypes.LICENSE_MODEL]: {
+        headerText: i18n('VLM'),
+        contentIconName: 'vlm',
+        color: 'purple'
+    },
+    [catalogItemTypes.SOFTWARE_PRODUCT]: {
+        headerText: i18n('VSP'),
+        contentIconName: 'vsp',
+        color: 'blue'
+    }
 };
 
-const CatalogItemDetails = ({catalogItemData, catalogItemTypeClass, onSelect, onMigrate}) => {
+const CatalogItemDetails = ({
+    catalogItemData,
+    catalogItemTypeClass,
+    onSelect,
+    onMigrate
+}) => {
+    let { vendorName, name, owner } = catalogItemData;
+    let { headerText, color, contentIconName } = ITEM_TYPE_MAP[
+        catalogItemTypeClass
+    ];
 
-       let {vendorName, name, owner} = catalogItemData;
-       let {headerText, color, contentIconName} = ITEM_TYPE_MAP[catalogItemTypeClass];
-
-       let onClick = (e) => {
-               e.stopPropagation();
-               e.preventDefault();
-               if (catalogItemData.isOldVersion && catalogItemData.isOldVersion === migrationStatusMapper.OLD_VERSION) {
-                       onMigrate({softwareProduct: catalogItemData});
-               } else {
-                       onSelect();
-               }
-       };
-
-       return (
-               <Tile
-                       headerText={headerText}
-                       headerColor={color}
-                       iconName={contentIconName}
-                       iconColor={color}
-                       onClick={onClick}
-                       dataTestId={catalogItemTypeClass}>
-                       <TileInfo data-test-id='catalog-item-content'>
-                               {vendorName &&
-                                       <TileInfoLine type='supertitle'>
-                                               <TooltipWrapper className='with-overlay' tooltipClassName='tile-super-info' dataTestId='catalog-item-vendor-name'>{vendorName}</TooltipWrapper>
-                                       </TileInfoLine>
-                               }
-                               <TileInfoLine type='title'>
-                                       <TooltipWrapper className='with-overlay' tooltipClassName='tile-title-info' dataTestId='catalog-item-name'>{name}</TooltipWrapper>
-                               </TileInfoLine>
-                       </TileInfo>
-                               <TileFooter>
-                               {owner &&
-                                       <TileFooterCell>Owner - {owner}</TileFooterCell>
-                               }
-                               </TileFooter>
-               </Tile>
-       );
+    let onClick = e => {
+        e.stopPropagation();
+        e.preventDefault();
+        if (
+            catalogItemData.isOldVersion &&
+            catalogItemData.isOldVersion === migrationStatusMapper.OLD_VERSION
+        ) {
+            onMigrate({ softwareProduct: catalogItemData });
+        } else {
+            onSelect();
+        }
+    };
 
+    return (
+        <Tile
+            headerText={headerText}
+            headerColor={color}
+            iconName={contentIconName}
+            iconColor={color}
+            onClick={onClick}
+            dataTestId={catalogItemTypeClass}>
+            <TileInfo data-test-id="catalog-item-content">
+                {vendorName && (
+                    <TileInfoLine type="supertitle">
+                        <TooltipWrapper
+                            className="with-overlay"
+                            tooltipClassName="tile-super-info"
+                            dataTestId="catalog-item-vendor-name">
+                            {vendorName}
+                        </TooltipWrapper>
+                    </TileInfoLine>
+                )}
+                <TileInfoLine type="title">
+                    <TooltipWrapper
+                        className="with-overlay"
+                        tooltipClassName="tile-title-info"
+                        dataTestId="catalog-item-name">
+                        {name}
+                    </TooltipWrapper>
+                </TileInfoLine>
+            </TileInfo>
+            <TileFooter>
+                {owner && <TileFooterCell>Owner - {owner}</TileFooterCell>}
+            </TileFooter>
+        </Tile>
+    );
 };
 
 CatalogItemDetails.PropTypes = {
-       catalogItemData: PropTypes.obj,
-       catalogItemTypeClass: PropTypes.string,
-       onSelect: PropTypes.func,
-       onMigrate: PropTypes.func
+    catalogItemData: PropTypes.obj,
+    catalogItemTypeClass: PropTypes.string,
+    onSelect: PropTypes.func,
+    onMigrate: PropTypes.func
 };
 
 export default CatalogItemDetails;
index 156adfc..d01b9d0 100644 (file)
@@ -1,33 +1,48 @@
 import React from 'react';
-import {storiesOf, action} from '@kadira/storybook';
-import {select, withKnobs} from '@kadira/storybook-addon-knobs';
+import { storiesOf, action } from '@kadira/storybook';
+import { select, withKnobs } from '@kadira/storybook-addon-knobs';
 import CatalogItemDetails from './CatalogItemDetails.jsx';
-import {catalogItemTypes, catalogItemStatuses} from './onboardingCatalog/OnboardingCatalogConstants.js';
-import {FinalizedLicenseModelFactory} from 'test-utils/factories/licenseModel/LicenseModelFactories.js';
+import {
+    catalogItemTypes,
+    catalogItemStatuses
+} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import { FinalizedLicenseModelFactory } from 'test-utils/factories/licenseModel/LicenseModelFactories.js';
 
 const stories = storiesOf('CatalogTiles', module);
 stories.addDecorator(withKnobs);
 
 const types = [
-       catalogItemTypes.LICENSE_MODEL,
-       catalogItemTypes.SOFTWARE_PRODUCT
+    catalogItemTypes.LICENSE_MODEL,
+    catalogItemTypes.SOFTWARE_PRODUCT
 ];
 
 function selectType() {
-       return select('Item type' , types, types[0]);
+    return select('Item type', types, types[0]);
 }
 
-let vlm = {...FinalizedLicenseModelFactory.build({name: 'Test-VLM'}), itemStatus: catalogItemStatuses.DRAFT};
-let certifiedVlm = {...vlm, itemStatus: catalogItemStatuses.CERTIFIED};
+let vlm = {
+    ...FinalizedLicenseModelFactory.build({ name: 'Test-VLM' }),
+    itemStatus: catalogItemStatuses.DRAFT
+};
+let certifiedVlm = { ...vlm, itemStatus: catalogItemStatuses.CERTIFIED };
 
-stories
-       .add('preview', () => (
-               <div className='catalog-view'>
-                       <div className='catalog-list'>
-                               <div className='catalog-items'>
-                                       <CatalogItemDetails catalogItemData={vlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>
-                                       <CatalogItemDetails catalogItemData={certifiedVlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>
-                               </div>
-                       </div>
-               </div>
-       ));
+stories.add('preview', () => (
+    <div className="catalog-view">
+        <div className="catalog-list">
+            <div className="catalog-items">
+                <CatalogItemDetails
+                    catalogItemData={vlm}
+                    catalogItemTypeClass={selectType()}
+                    onSelect={action('onSelect')}
+                    onMigrate={action('onMigrate')}
+                />
+                <CatalogItemDetails
+                    catalogItemData={certifiedVlm}
+                    catalogItemTypeClass={selectType()}
+                    onSelect={action('onSelect')}
+                    onMigrate={action('onMigrate')}
+                />
+            </div>
+        </div>
+    </div>
+));
index 10d855c..b00ceeb 100644 (file)
@@ -17,37 +17,61 @@ import React from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 
-const SoftwareProductListHeader = ({selectedVendor, onBack}) => (
-       <div className='vendor-page-header'>
-               <SVGIcon name='back' onClick={onBack}/>
-               <div className='tab-separator' />
-               <div className='vendor-name'>{selectedVendor.name}</div>
-       </div>
+const SoftwareProductListHeader = ({ selectedVendor, onBack }) => (
+    <div className="vendor-page-header">
+        <SVGIcon name="back" onClick={onBack} />
+        <div className="tab-separator" />
+        <div className="vendor-name">{selectedVendor.name}</div>
+    </div>
 );
 
-const CatalogList = ({children, onAddVLM, onAddVSP, vendorPageOptions}) => (
-       <div className='catalog-list'>
-               {vendorPageOptions && <SoftwareProductListHeader onBack={vendorPageOptions.onBack} selectedVendor={vendorPageOptions.selectedVendor}/>}
-               <div className='catalog-items'>
-                       { (onAddVLM || onAddVSP) &&
-                               <div className='create-catalog-item-wrapper'>
-                                       {onAddVLM && <CreateItemTile onClick={onAddVLM} dataTestId={'catalog-add-new-vlm'} className='vlm-type' title={i18n('CREATE NEW VLM')}/>}
-                                       {onAddVSP && <CreateItemTile onClick={() => onAddVSP()} dataTestId={'catalog-add-new-vsp'} className='vsp-type' title={i18n('CREATE NEW VSP')}/>}
-                               </div>
-                       }
-                       {children}
-               </div>
-       </div>
+const CatalogList = ({ children, onAddVLM, onAddVSP, vendorPageOptions }) => (
+    <div className="catalog-list">
+        {vendorPageOptions && (
+            <SoftwareProductListHeader
+                onBack={vendorPageOptions.onBack}
+                selectedVendor={vendorPageOptions.selectedVendor}
+            />
+        )}
+        <div className="catalog-items">
+            {(onAddVLM || onAddVSP) && (
+                <div className="create-catalog-item-wrapper">
+                    {onAddVLM && (
+                        <CreateItemTile
+                            onClick={onAddVLM}
+                            dataTestId={'catalog-add-new-vlm'}
+                            className="vlm-type"
+                            title={i18n('CREATE NEW VLM')}
+                        />
+                    )}
+                    {onAddVSP && (
+                        <CreateItemTile
+                            onClick={() => onAddVSP()}
+                            dataTestId={'catalog-add-new-vsp'}
+                            className="vsp-type"
+                            title={i18n('CREATE NEW VSP')}
+                        />
+                    )}
+                </div>
+            )}
+            {children}
+        </div>
+    </div>
 );
 
-const CreateItemTile = ({onClick, dataTestId, title, className = ''}) => {
-       //TODO check for buttons
-       return (
-                       <div className={`create-catalog-item tile ${className}`} onClick={onClick} data-test-id={dataTestId}>
-                               <div className='create-item-plus-icon'><SVGIcon name='plus' /></div>
-                               <div className='create-item-text'>{title}</div>
-                       </div>
-       );
+const CreateItemTile = ({ onClick, dataTestId, title, className = '' }) => {
+    //TODO check for buttons
+    return (
+        <div
+            className={`create-catalog-item tile ${className}`}
+            onClick={onClick}
+            data-test-id={dataTestId}>
+            <div className="create-item-plus-icon">
+                <SVGIcon name="plus" />
+            </div>
+            <div className="create-item-text">{title}</div>
+        </div>
+    );
 };
 
 export default CatalogList;
index 1ef9c82..90496c9 100644 (file)
  * permissions and limitations under the License.
  */
 import React from 'react';
-import {modalMapper, catalogItemTypes, catalogItemTypeClasses } from './onboardingCatalog/OnboardingCatalogConstants.js';
+import {
+    modalMapper,
+    catalogItemTypes,
+    catalogItemTypeClasses
+} from './onboardingCatalog/OnboardingCatalogConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Modal from 'nfvo-components/modal/Modal.jsx';
 import LicenseModelCreation from '../licenseModel/creation/LicenseModelCreation.js';
 import SoftwareProductCreation from '../softwareProduct/creation/SoftwareProductCreation.js';
 
-class CatalogModal extends React.Component{
+class CatalogModal extends React.Component {
+    getModalDetails() {
+        const { modalToShow } = this.props;
+        switch (modalToShow) {
+            case catalogItemTypes.LICENSE_MODEL:
+                return {
+                    title: i18n('New License Model'),
+                    element: <LicenseModelCreation />
+                };
+            case catalogItemTypes.SOFTWARE_PRODUCT:
+                return {
+                    title: i18n('New Software Product'),
+                    element: <SoftwareProductCreation />
+                };
+        }
+    }
 
-       getModalDetails(){
-               const {modalToShow} = this.props;
-               switch (modalToShow) {
-                       case catalogItemTypes.LICENSE_MODEL:
-                               return {
-                                       title: i18n('New License Model'),
-                                       element: <LicenseModelCreation/>
-                               };
-                       case catalogItemTypes.SOFTWARE_PRODUCT:
-                               return {
-                                       title: i18n('New Software Product'),
-                                       element: <SoftwareProductCreation/>
-                               };
-               }
-       }
+    render() {
+        const { modalToShow } = this.props;
+        const modalDetails = this.getModalDetails(modalToShow);
 
-       render(){
-               const {modalToShow} = this.props;
-               const modalDetails = this.getModalDetails(modalToShow);
-
-               return (
-                       <Modal
-                               show={Boolean(modalDetails)}
-                               className={`${catalogItemTypeClasses[modalMapper[modalToShow]]}-modal`}>
-                               <Modal.Header>
-                                       <Modal.Title>{modalDetails && modalDetails.title}</Modal.Title>
-                               </Modal.Header>
-                               <Modal.Body>
-                                       {
-                                               modalDetails && modalDetails.element
-                                       }
-                               </Modal.Body>
-                       </Modal>
-               );
-       }
+        return (
+            <Modal
+                show={Boolean(modalDetails)}
+                className={`${
+                    catalogItemTypeClasses[modalMapper[modalToShow]]
+                }-modal`}>
+                <Modal.Header>
+                    <Modal.Title>
+                        {modalDetails && modalDetails.title}
+                    </Modal.Title>
+                </Modal.Header>
+                <Modal.Body>{modalDetails && modalDetails.element}</Modal.Body>
+            </Modal>
+        );
+    }
 }
 
 export default CatalogModal;
index ea6cf5e..771c0eb 100644 (file)
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import {catalogItemTypes} from './onboardingCatalog/OnboardingCatalogConstants.js';
-import {filterCatalogItemsByType} from './onboardingCatalog/OnboardingCatalogUtils.js';
+import { catalogItemTypes } from './onboardingCatalog/OnboardingCatalogConstants.js';
+import { filterCatalogItemsByType } from './onboardingCatalog/OnboardingCatalogUtils.js';
 import CatalogList from './CatalogList.jsx';
 import CatalogItemDetails from './CatalogItemDetails.jsx';
 
-class DetailsCatalogView extends React.Component{
+class DetailsCatalogView extends React.Component {
+    static propTypes = {
+        VLMList: PropTypes.array,
+        VSPList: PropTypes.array,
+        onSelectVLM: PropTypes.func.isRequired,
+        onSelectVSP: PropTypes.func.isRequired,
+        onAddVLM: PropTypes.func,
+        onAddVSP: PropTypes.func,
+        filter: PropTypes.string.isRequired
+    };
 
-       static propTypes = {
-               VLMList: PropTypes.array,
-               VSPList: PropTypes.array,
-               onSelectVLM: PropTypes.func.isRequired,
-               onSelectVSP: PropTypes.func.isRequired,
-               onAddVLM: PropTypes.func,
-               onAddVSP: PropTypes.func,
-               filter: PropTypes.string.isRequired
-       };
+    renderCatalogItems({ items, type, filter, onSelect, onMigrate, users }) {
+        return filterCatalogItemsByType({ items, filter }).map(item => (
+            <CatalogItemDetails
+                key={item.id}
+                catalogItemData={item}
+                catalogItemTypeClass={type}
+                onMigrate={onMigrate}
+                onSelect={() => onSelect(item, users)}
+            />
+        ));
+    }
 
-       renderCatalogItems({items, type, filter, onSelect, onMigrate, users}){
-               return filterCatalogItemsByType({items, filter}).map(item =>
-                       <CatalogItemDetails
-                               key={item.id}
-                               catalogItemData={item}
-                               catalogItemTypeClass={type}
-                               onMigrate={onMigrate}
-                               onSelect={() => onSelect(item, users)} />
-               );
-       }
-
-       render() {
-               let {VLMList, VSPList, users, onAddVSP, onAddVLM, onSelectVLM, onSelectVSP, filter = '', onMigrate} = this.props;
-               return (
-                       <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
-                               {this.renderCatalogItems({items: VLMList, type: catalogItemTypes.LICENSE_MODEL, filter, onSelect: onSelectVLM, onMigrate, users})}
-                               {this.renderCatalogItems({items: VSPList, type: catalogItemTypes.SOFTWARE_PRODUCT, filter, onSelect: onSelectVSP, onMigrate, users})}
-                       </CatalogList>
-               );
-       }
+    render() {
+        let {
+            VLMList,
+            VSPList,
+            users,
+            onAddVSP,
+            onAddVLM,
+            onSelectVLM,
+            onSelectVSP,
+            filter = '',
+            onMigrate
+        } = this.props;
+        return (
+            <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+                {this.renderCatalogItems({
+                    items: VLMList,
+                    type: catalogItemTypes.LICENSE_MODEL,
+                    filter,
+                    onSelect: onSelectVLM,
+                    onMigrate,
+                    users
+                })}
+                {this.renderCatalogItems({
+                    items: VSPList,
+                    type: catalogItemTypes.SOFTWARE_PRODUCT,
+                    filter,
+                    onSelect: onSelectVSP,
+                    onMigrate,
+                    users
+                })}
+            </CatalogList>
+        );
+    }
 }
 export default DetailsCatalogView;
index 9535147..a1e0018 100644 (file)
  * limitations under the License.
  */
 
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import OnboardView from './OnboardView.jsx';
 import OnboardingCatalogActionHelper from './onboardingCatalog/OnboardingCatalogActionHelper.js';
 import OnboardActionHelper from './OnboardActionHelper.js';
 import LicenseModelCreationActionHelper from '../licenseModel/creation/LicenseModelCreationActionHelper.js';
 import SoftwareProductCreationActionHelper from '../softwareProduct/creation/SoftwareProductCreationActionHelper.js';
 import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
-import {tabsMapping} from './onboardingCatalog/OnboardingCatalogConstants.js';
-import {itemsType} from './filter/FilterConstants.js';
+import { tabsMapping } from './onboardingCatalog/OnboardingCatalogConstants.js';
+import { itemsType } from './filter/FilterConstants.js';
 
 export const mapStateToProps = ({
-       onboard: {
-               onboardingCatalog,
-               activeTab,
-               searchValue,
-               filter
-       },
-       licenseModelList,
-       users,
-       archivedLicenseModelList,
-       archivedSoftwareProductList,
-       finalizedLicenseModelList,
-       softwareProductList,
-       finalizedSoftwareProductList
+    onboard: { onboardingCatalog, activeTab, searchValue, filter },
+    licenseModelList,
+    users,
+    archivedLicenseModelList,
+    archivedSoftwareProductList,
+    finalizedLicenseModelList,
+    softwareProductList,
+    finalizedSoftwareProductList
 }) => {
+    const fullSoftwareProducts = softwareProductList
+        .filter(
+            vsp =>
+                !finalizedSoftwareProductList.find(fvsp => fvsp.id === vsp.id)
+        )
+        .concat(finalizedSoftwareProductList);
 
-       const fullSoftwareProducts = softwareProductList.filter(vsp =>
-               !finalizedSoftwareProductList
-                       .find(fvsp => fvsp.id === vsp.id)
-       ).concat(finalizedSoftwareProductList);
+    const reduceLicenseModelList = (accum, vlm) => {
+        let currentSoftwareProductList = sortByStringProperty(
+            fullSoftwareProducts.filter(vsp => vsp.vendorId === vlm.id),
+            'name'
+        );
+        accum.push({ ...vlm, softwareProductList: currentSoftwareProductList });
+        return accum;
+    };
 
-       const reduceLicenseModelList = (accum, vlm) => {
-               let currentSoftwareProductList = sortByStringProperty(
-                       fullSoftwareProducts
-                               .filter(vsp => vsp.vendorId === vlm.id),
-                       'name'
-               );
-               accum.push({...vlm, softwareProductList: currentSoftwareProductList});
-               return accum;
-       };
+    licenseModelList = sortByStringProperty(
+        licenseModelList.reduce(reduceLicenseModelList, []),
+        'name'
+    );
 
-       licenseModelList = sortByStringProperty(
-               licenseModelList
-                       .reduce(reduceLicenseModelList, []),
-               'name'
-       );
+    finalizedLicenseModelList = sortByStringProperty(
+        finalizedLicenseModelList.reduce(reduceLicenseModelList, []),
+        'name'
+    );
 
-       finalizedLicenseModelList = sortByStringProperty(
-               finalizedLicenseModelList
-                       .reduce(reduceLicenseModelList, []),
-               'name'
-       );
+    const fullLicenseModelList = licenseModelList
+        .filter(
+            vlm => !finalizedLicenseModelList.find(fvlm => fvlm.id === vlm.id)
+        )
+        .concat(finalizedLicenseModelList);
 
-       const fullLicenseModelList = licenseModelList.filter(vlm =>
-               !finalizedLicenseModelList
-                       .find(fvlm => fvlm.id === vlm.id)
-       ).concat(finalizedLicenseModelList);
-
-       let {activeTab: catalogActiveTab, vendorCatalog: {vspOverlay, selectedVendor}} = onboardingCatalog;
-       if (filter.byVendorView) {
-               catalogActiveTab = tabsMapping.BY_VENDOR;
-       } 
-       else if (filter.itemsType && filter.itemsType === itemsType.ARCHIVED) {
-               catalogActiveTab = tabsMapping.ARCHIVE;
-       }
-
-       return {
-               finalizedLicenseModelList,
-               finalizedSoftwareProductList,
-               licenseModelList,
-               softwareProductList,
-               archivedLicenseModelList,
-               archivedSoftwareProductList,
-               fullLicenseModelList,
-               activeTab,
-               catalogActiveTab,
-               searchValue,
-               vspOverlay,
-               selectedVendor,
-               users: users.usersList
-       };
+    let {
+        activeTab: catalogActiveTab,
+        vendorCatalog: { vspOverlay, selectedVendor }
+    } = onboardingCatalog;
+    if (filter.byVendorView) {
+        catalogActiveTab = tabsMapping.BY_VENDOR;
+    } else if (filter.itemsType && filter.itemsType === itemsType.ARCHIVED) {
+        catalogActiveTab = tabsMapping.ARCHIVE;
+    }
 
+    return {
+        finalizedLicenseModelList,
+        finalizedSoftwareProductList,
+        licenseModelList,
+        softwareProductList,
+        archivedLicenseModelList,
+        archivedSoftwareProductList,
+        fullLicenseModelList,
+        activeTab,
+        catalogActiveTab,
+        searchValue,
+        vspOverlay,
+        selectedVendor,
+        users: users.usersList
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-
-       return {
-               onSelectLicenseModel({id: licenseModelId, name}, users, tab) {
-                       OnboardActionHelper.loadVLMScreen(dispatch, {id: licenseModelId, name}, users, tab);
-               },
-               onSelectSoftwareProduct(softwareProduct, users, tab) {
-                       OnboardActionHelper.loadVSPScreen(dispatch, softwareProduct, users, tab);
-               },
-               onAddSoftwareProductClick: (vendorId) => SoftwareProductCreationActionHelper.open(dispatch, vendorId),
-               onAddLicenseModelClick: () => LicenseModelCreationActionHelper.open(dispatch),
-               onVspOverlayChange: (vendor) => OnboardingCatalogActionHelper.changeVspOverlay(dispatch, vendor),
-               closeVspOverlay: () => OnboardingCatalogActionHelper.closeVspOverlay(dispatch),
-               onCatalogTabClick: (tab) => OnboardingCatalogActionHelper.changeActiveTab(dispatch, tab),
-               onTabClick: (tab) => OnboardActionHelper.changeActiveTab(dispatch, tab),
-               onSearch: (searchValue) => OnboardActionHelper.changeSearchValue(dispatch, searchValue),
-               onVendorSelect: (vendor) => OnboardingCatalogActionHelper.onVendorSelect(dispatch, {vendor}),
-               onMigrate: ({softwareProduct}) => OnboardingCatalogActionHelper.onMigrate(dispatch, softwareProduct)
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onSelectLicenseModel({ id: licenseModelId, name }, users, tab) {
+            OnboardActionHelper.loadVLMScreen(
+                dispatch,
+                { id: licenseModelId, name },
+                users,
+                tab
+            );
+        },
+        onSelectSoftwareProduct(softwareProduct, users, tab) {
+            OnboardActionHelper.loadVSPScreen(
+                dispatch,
+                softwareProduct,
+                users,
+                tab
+            );
+        },
+        onAddSoftwareProductClick: vendorId =>
+            SoftwareProductCreationActionHelper.open(dispatch, vendorId),
+        onAddLicenseModelClick: () =>
+            LicenseModelCreationActionHelper.open(dispatch),
+        onVspOverlayChange: vendor =>
+            OnboardingCatalogActionHelper.changeVspOverlay(dispatch, vendor),
+        closeVspOverlay: () =>
+            OnboardingCatalogActionHelper.closeVspOverlay(dispatch),
+        onCatalogTabClick: tab =>
+            OnboardingCatalogActionHelper.changeActiveTab(dispatch, tab),
+        onTabClick: tab => OnboardActionHelper.changeActiveTab(dispatch, tab),
+        onSearch: searchValue =>
+            OnboardActionHelper.changeSearchValue(dispatch, searchValue),
+        onVendorSelect: vendor =>
+            OnboardingCatalogActionHelper.onVendorSelect(dispatch, { vendor }),
+        onMigrate: ({ softwareProduct }) =>
+            OnboardingCatalogActionHelper.onMigrate(dispatch, softwareProduct)
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(OnboardView);
index 8920568..87ec2d1 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {tabsMapping, actionTypes} from './OnboardConstants.js';
+import { tabsMapping, actionTypes } from './OnboardConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
-import {itemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
 
 const OnboardActionHelper = {
-       resetOnboardStore(dispatch) {
-               dispatch({
-                       type: actionTypes.RESET_ONBOARD_STORE
-               });
-       },
-       changeActiveTab(dispatch, activeTab) {
-               this.clearSearchValue(dispatch);
-               dispatch({
-                       type: actionTypes.CHANGE_ACTIVE_ONBOARD_TAB,
-                       activeTab
-               });
-       },
-       changeSearchValue(dispatch, searchValue) {
-               dispatch({
-                       type: actionTypes.CHANGE_SEARCH_VALUE,
-                       searchValue
-               });
-       },
-       clearSearchValue(dispatch) {
-               dispatch({
-                       type: actionTypes.CHANGE_SEARCH_VALUE,
-                       searchValue: ''
-               });
-       },
+    resetOnboardStore(dispatch) {
+        dispatch({
+            type: actionTypes.RESET_ONBOARD_STORE
+        });
+    },
+    changeActiveTab(dispatch, activeTab) {
+        this.clearSearchValue(dispatch);
+        dispatch({
+            type: actionTypes.CHANGE_ACTIVE_ONBOARD_TAB,
+            activeTab
+        });
+    },
+    changeSearchValue(dispatch, searchValue) {
+        dispatch({
+            type: actionTypes.CHANGE_SEARCH_VALUE,
+            searchValue
+        });
+    },
+    clearSearchValue(dispatch) {
+        dispatch({
+            type: actionTypes.CHANGE_SEARCH_VALUE,
+            searchValue: ''
+        });
+    },
 
-       loadVLMScreen(dispatch, {id: licenseModelId, name}, users, tab) {
-               if (tab === tabsMapping.WORKSPACE) {
-                       VersionsPageActionHelper.fetchVersions(dispatch, {itemId: licenseModelId, itemType: itemTypes.LICENSE_MODEL}).then(({results})=> {
-                               results = results.filter((version) => version.status === catalogItemStatuses.DRAFT);
-                               if (results.length !== 1) {
-                                       ScreensHelper.loadScreen(dispatch, {
-                                               screen: enums.SCREEN.VERSIONS_PAGE, screenType: screenTypes.LICENSE_MODEL,
-                                               props: {licenseModelId, licenseModel: {name}, usersList: users}
-                                       });
-                               }
-                               else {
-                                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId: licenseModelId, allUsers: users}).then(() =>
-                                               ScreensHelper.loadLandingScreen(dispatch, {screenType: screenTypes.LICENSE_MODEL, props: {licenseModelId, version: results[0]}})
-                                       );
-                               }
-                       });
-               }
-               if (tab === tabsMapping.CATALOG) {
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: enums.SCREEN.VERSIONS_PAGE, screenType: screenTypes.LICENSE_MODEL,
-                               props: {licenseModelId, licenseModel: {name}, usersList: users}
-                       });
-               }
-       },
-       loadVSPScreen(dispatch, softwareProduct, users, tab) {
-               let {id: softwareProductId, vendorId: licenseModelId, licensingVersion, name} = softwareProduct;
-               if (tab === tabsMapping.WORKSPACE) {
-                       VersionsPageActionHelper.fetchVersions(dispatch,{itemId: softwareProductId, itemType: itemTypes.SOFTWARE_PRODUCT}).then(({results})=> {
-                               results = results.filter((version) => version.status === catalogItemStatuses.DRAFT);
-                               if (results.length !== 1) {
-                                       ScreensHelper.loadScreen(dispatch, {
-                                               screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {
-                                                       softwareProductId,
-                                                       softwareProduct: {name, vendorId: licenseModelId, licensingVersion},
-                                                       usersList: users
-                                               }
-                                       });
-                               }
-                               else {
-                                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId: softwareProductId, allUsers: users}).then(() =>
-                                               ScreensHelper.loadLandingScreen(dispatch, {screenType: screenTypes.SOFTWARE_PRODUCT, props: {softwareProductId, licenseModelId, version: results[0]}})
-                                       );
-                               }
-                       });
-               }
-               if (tab === tabsMapping.CATALOG) {
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                               props: {
-                                       softwareProductId,
-                                       softwareProduct: {name, vendorId: licenseModelId, licensingVersion},
-                                       usersList: users
-                               }
-                       });
-               }
-       }
+    loadVLMScreen(dispatch, { id: licenseModelId, name }, users, tab) {
+        if (tab === tabsMapping.WORKSPACE) {
+            VersionsPageActionHelper.fetchVersions(dispatch, {
+                itemId: licenseModelId,
+                itemType: itemTypes.LICENSE_MODEL
+            }).then(({ results }) => {
+                results = results.filter(
+                    version => version.status === catalogItemStatuses.DRAFT
+                );
+                if (results.length !== 1) {
+                    ScreensHelper.loadScreen(dispatch, {
+                        screen: enums.SCREEN.VERSIONS_PAGE,
+                        screenType: screenTypes.LICENSE_MODEL,
+                        props: {
+                            licenseModelId,
+                            licenseModel: { name },
+                            usersList: users
+                        }
+                    });
+                } else {
+                    PermissionsActionHelper.fetchItemUsers(dispatch, {
+                        itemId: licenseModelId,
+                        allUsers: users
+                    }).then(() =>
+                        ScreensHelper.loadLandingScreen(dispatch, {
+                            screenType: screenTypes.LICENSE_MODEL,
+                            props: { licenseModelId, version: results[0] }
+                        })
+                    );
+                }
+            });
+        }
+        if (tab === tabsMapping.CATALOG) {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.VERSIONS_PAGE,
+                screenType: screenTypes.LICENSE_MODEL,
+                props: {
+                    licenseModelId,
+                    licenseModel: { name },
+                    usersList: users
+                }
+            });
+        }
+    },
+    loadVSPScreen(dispatch, softwareProduct, users, tab) {
+        let {
+            id: softwareProductId,
+            vendorId: licenseModelId,
+            licensingVersion,
+            name
+        } = softwareProduct;
+        if (tab === tabsMapping.WORKSPACE) {
+            VersionsPageActionHelper.fetchVersions(dispatch, {
+                itemId: softwareProductId,
+                itemType: itemTypes.SOFTWARE_PRODUCT
+            }).then(({ results }) => {
+                results = results.filter(
+                    version => version.status === catalogItemStatuses.DRAFT
+                );
+                if (results.length !== 1) {
+                    ScreensHelper.loadScreen(dispatch, {
+                        screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE,
+                        screenType: screenTypes.SOFTWARE_PRODUCT,
+                        props: {
+                            softwareProductId,
+                            softwareProduct: {
+                                name,
+                                vendorId: licenseModelId,
+                                licensingVersion
+                            },
+                            usersList: users
+                        }
+                    });
+                } else {
+                    PermissionsActionHelper.fetchItemUsers(dispatch, {
+                        itemId: softwareProductId,
+                        allUsers: users
+                    }).then(() =>
+                        ScreensHelper.loadLandingScreen(dispatch, {
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                licenseModelId,
+                                version: results[0]
+                            }
+                        })
+                    );
+                }
+            });
+        }
+        if (tab === tabsMapping.CATALOG) {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: {
+                    softwareProductId,
+                    softwareProduct: {
+                        name,
+                        vendorId: licenseModelId,
+                        licensingVersion
+                    },
+                    usersList: users
+                }
+            });
+        }
+    }
 };
 
 export default OnboardActionHelper;
index 41128bf..6fbf265 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const tabsMapping = {
-       'WORKSPACE': 1,
-       'CATALOG': 2
+    WORKSPACE: 1,
+    CATALOG: 2
 };
 
 export const actionTypes = keyMirror({
-       CHANGE_ACTIVE_ONBOARD_TAB: null,
-       CHANGE_SEARCH_VALUE: null,
-       RESET_ONBOARD_STORE: null,
-       VSP_MIGRATION: null
+    CHANGE_ACTIVE_ONBOARD_TAB: null,
+    CHANGE_SEARCH_VALUE: null,
+    RESET_ONBOARD_STORE: null,
+    VSP_MIGRATION: null
 });
index b2e7b04..39ceb31 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, tabsMapping} from './OnboardConstants.js';
-import {combineReducers} from 'redux';
+import { actionTypes, tabsMapping } from './OnboardConstants.js';
+import { combineReducers } from 'redux';
 import onboardingCatalogReducer from './onboardingCatalog/OnboardingCatalogReducer.js';
 import filterReducer from './filter/FilterReducer.js';
 
 const onboardReducer = combineReducers({
-       onboardingCatalog: onboardingCatalogReducer,
-       filter: filterReducer,
-       activeTab: (state = tabsMapping.WORKSPACE, action) => action.type === actionTypes.CHANGE_ACTIVE_ONBOARD_TAB ? action.activeTab : state,
-       searchValue: (state = '', action) => action.type === actionTypes.CHANGE_SEARCH_VALUE ? action.searchValue : state
+    onboardingCatalog: onboardingCatalogReducer,
+    filter: filterReducer,
+    activeTab: (state = tabsMapping.WORKSPACE, action) =>
+        action.type === actionTypes.CHANGE_ACTIVE_ONBOARD_TAB
+            ? action.activeTab
+            : state,
+    searchValue: (state = '', action) =>
+        action.type === actionTypes.CHANGE_SEARCH_VALUE
+            ? action.searchValue
+            : state
 });
 
 export default (state, action) => {
-       if (action.type === actionTypes.RESET_ONBOARD_STORE) {
-               state = undefined;
-       }
-       return onboardReducer(state, action);
+    if (action.type === actionTypes.RESET_ONBOARD_STORE) {
+        state = undefined;
+    }
+    return onboardReducer(state, action);
 };
index c045a37..dcaeaa7 100644 (file)
@@ -17,89 +17,99 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import OnboardingCatalogView from './onboardingCatalog/OnboardingCatalogView.jsx';
 import WorkspaceView from './workspace/WorkspaceView.jsx';
-import {tabsMapping} from './OnboardConstants.js';
+import { tabsMapping } from './OnboardConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import classnames from 'classnames';
 import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
 import objectValues from 'lodash/values.js';
-import {catalogItemTypes} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import { catalogItemTypes } from './onboardingCatalog/OnboardingCatalogConstants.js';
 import NotificationsView from 'sdc-app/onboarding/userNotifications/NotificationsView.jsx';
 import Filter from 'sdc-app/onboarding/onboard/filter/Filter.jsx';
 
-const OnboardHeaderTabs = ({onTabClick, activeTab}) => (
-       <div className='onboard-header-tabs'>
-               <div
-                       className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.WORKSPACE })}
-                       onClick={() => onTabClick(tabsMapping.WORKSPACE)}
-                       data-test-id='onboard-workspace-tab'>
-                       {i18n('WORKSPACE')}
-               </div>
-               <div
-                       className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.CATALOG })}
-                       onClick={() => onTabClick(tabsMapping.CATALOG)}
-                       data-test-id='onboard-onboard-tab'>
-                       {i18n('ONBOARD CATALOG')}
-               </div>
-       </div>
+const OnboardHeaderTabs = ({ onTabClick, activeTab }) => (
+    <div className="onboard-header-tabs">
+        <div
+            className={classnames('onboard-header-tab', {
+                active: activeTab === tabsMapping.WORKSPACE
+            })}
+            onClick={() => onTabClick(tabsMapping.WORKSPACE)}
+            data-test-id="onboard-workspace-tab">
+            {i18n('WORKSPACE')}
+        </div>
+        <div
+            className={classnames('onboard-header-tab', {
+                active: activeTab === tabsMapping.CATALOG
+            })}
+            onClick={() => onTabClick(tabsMapping.CATALOG)}
+            data-test-id="onboard-onboard-tab">
+            {i18n('ONBOARD CATALOG')}
+        </div>
+    </div>
 );
 
-const OnboardHeader = ({onSearch, activeTab, onTabClick, searchValue}) => (
-       <div className='onboard-header'>
-               <OnboardHeaderTabs activeTab={activeTab} onTabClick={onTabClick} />
-               <ExpandableInput
-                       onChange={onSearch}
-                       iconType='search'
-                       value={searchValue}/>
-               <NotificationsView />
-       </div>
+const OnboardHeader = ({ onSearch, activeTab, onTabClick, searchValue }) => (
+    <div className="onboard-header">
+        <OnboardHeaderTabs activeTab={activeTab} onTabClick={onTabClick} />
+        <ExpandableInput
+            onChange={onSearch}
+            iconType="search"
+            value={searchValue}
+        />
+        <NotificationsView />
+    </div>
 );
 
 class OnboardView extends React.Component {
-       static propTypes = {
-               licenseModelList: PropTypes.array,
-               softwareProductList: PropTypes.array,
-               finalizedLicenseModelList: PropTypes.array,
-               finalizedSoftwareProductList: PropTypes.array,
-               archivedSoftwareProductList: PropTypes.array,
-               archivedLicenseModelList: PropTypes.array,
-               modalToShow: PropTypes.oneOf(objectValues(catalogItemTypes)),
-               onSelectLicenseModel: PropTypes.func.isRequired,
-               onSelectSoftwareProduct: PropTypes.func.isRequired,
-               onAddLicenseModelClick: PropTypes.func.isRequired,
-               onAddSoftwareProductClick: PropTypes.func.isRequired,
-               closeVspOverlay: PropTypes.func.isRequired,
-               onVspOverlayChange: PropTypes.func.isRequired,
-               onTabClick: PropTypes.func.isRequired,
-               onCatalogTabClick: PropTypes.func.isRequired,
-               onSearch: PropTypes.func.isRequired,
-               activeTab: PropTypes.number.isRequired,
-               catalogActiveTab: PropTypes.number.isRequired,
-               searchValue: PropTypes.string.isRequired,
-               onMigrate: PropTypes.func.isRequired,
-       };
-       renderViewByTab(activeTab){
-               switch (activeTab){
-                       case tabsMapping.WORKSPACE:
-                               return <WorkspaceView {...this.props} />;
-                       case tabsMapping.CATALOG:
-                               return <OnboardingCatalogView {...this.props} />;
-                       default:
-                               return <WorkspaceView {...this.props} />;
-               }
-       }
+    static propTypes = {
+        licenseModelList: PropTypes.array,
+        softwareProductList: PropTypes.array,
+        finalizedLicenseModelList: PropTypes.array,
+        finalizedSoftwareProductList: PropTypes.array,
+        archivedSoftwareProductList: PropTypes.array,
+        archivedLicenseModelList: PropTypes.array,
+        modalToShow: PropTypes.oneOf(objectValues(catalogItemTypes)),
+        onSelectLicenseModel: PropTypes.func.isRequired,
+        onSelectSoftwareProduct: PropTypes.func.isRequired,
+        onAddLicenseModelClick: PropTypes.func.isRequired,
+        onAddSoftwareProductClick: PropTypes.func.isRequired,
+        closeVspOverlay: PropTypes.func.isRequired,
+        onVspOverlayChange: PropTypes.func.isRequired,
+        onTabClick: PropTypes.func.isRequired,
+        onCatalogTabClick: PropTypes.func.isRequired,
+        onSearch: PropTypes.func.isRequired,
+        activeTab: PropTypes.number.isRequired,
+        catalogActiveTab: PropTypes.number.isRequired,
+        searchValue: PropTypes.string.isRequired,
+        onMigrate: PropTypes.func.isRequired
+    };
+    renderViewByTab(activeTab) {
+        switch (activeTab) {
+            case tabsMapping.WORKSPACE:
+                return <WorkspaceView {...this.props} />;
+            case tabsMapping.CATALOG:
+                return <OnboardingCatalogView {...this.props} />;
+            default:
+                return <WorkspaceView {...this.props} />;
+        }
+    }
 
-       render() {
-               let {activeTab, onTabClick, onSearch, searchValue} = this.props;
-               return (
-                       <div className='catalog-view'>
-                               <Filter/>
-                               <div className='catalog-parts'>
-                                       <OnboardHeader activeTab={activeTab} onTabClick={onTabClick} searchValue={searchValue} onSearch={value => onSearch(value)}/>
-                                       {this.renderViewByTab(activeTab)}
-                               </div>
-                       </div>
-               );
-       }
+    render() {
+        let { activeTab, onTabClick, onSearch, searchValue } = this.props;
+        return (
+            <div className="catalog-view">
+                <Filter />
+                <div className="catalog-parts">
+                    <OnboardHeader
+                        activeTab={activeTab}
+                        onTabClick={onTabClick}
+                        searchValue={searchValue}
+                        onSearch={value => onSearch(value)}
+                    />
+                    {this.renderViewByTab(activeTab)}
+                </div>
+            </div>
+        );
+    }
 }
 
 export default OnboardView;
index d8d04f2..c80232d 100644 (file)
  * limitations under the License.
  */
 
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 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 Accordion from 'nfvo-components/accordion/Accordion.jsx';
-import {actionTypes} from './FilterConstants.js';
+import { actionTypes } from './FilterConstants.js';
 import featureToggle from 'sdc-app/features/featureToggle.js';
-import {featureToggleNames} from 'sdc-app/features/FeaturesConstants.js';
-import {tabsMapping as onboardTabsMapping} from '../OnboardConstants.js';
-import {itemsType as itemsTypeConstants} from './FilterConstants.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
+import { tabsMapping as onboardTabsMapping } from '../OnboardConstants.js';
+import { itemsType as itemsTypeConstants } from './FilterConstants.js';
 
-const mapStateToProps = ({onboard: {filter, activeTab}}) => {
-       return {
-               data: filter,
-               activeTab
-       };
+const mapStateToProps = ({ onboard: { filter, activeTab } }) => {
+    return {
+        data: filter,
+        activeTab
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData) => 
-                       dispatch({
-                               type: actionTypes.FILTER_DATA_CHANGED,
-                               deltaData
-                       })              
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: deltaData =>
+            dispatch({
+                type: actionTypes.FILTER_DATA_CHANGED,
+                deltaData
+            })
+    };
 };
 
-const Filter = ({onDataChanged, data: {entityTypeVsp, entityTypeVlm, roleOwner, roleContributor, roleViewer,
-                procedureNetwork, procedureManual, recentlyUpdated, byVendorView, itemsType}, activeTab}) => (
-    <div className='catalog-filter'>                   
-                {activeTab === onboardTabsMapping.CATALOG && <Input
-                       type='select'
-                       className='catalog-filter-items-type'
-                       data-test-id='catalog-filter-items-type' 
-                       disabled={byVendorView}
-                       value={itemsType}
-                       onChange={e => onDataChanged({itemsType: e.target.value})}>
-                               <option key={itemsTypeConstants.ACTIVE} value={itemsTypeConstants.ACTIVE}>Active Items</option>
-                               <option key={itemsTypeConstants.ARCHIVED} value={itemsTypeConstants.ARCHIVED}>Archived Items</option>
-               </Input>}
-               {activeTab === onboardTabsMapping.CATALOG && <Input 
-                       label={i18n('By Vendor View')}
-                        type='checkbox'
-                        disabled={itemsType === itemsTypeConstants.ARCHIVED} 
-                        checked={byVendorView} 
-                        onChange={byVendorView => onDataChanged({byVendorView})}
-                        data-test-id='filter-by-vendor-view' value='' />
-               }
-        <Input label={i18n('Recently Updated')} type='checkbox' checked={recentlyUpdated} 
-       onChange={recentlyUpdated => onDataChanged({recentlyUpdated})}  data-test-id='filter-recently-updated' value='' />
+const Filter = ({
+    onDataChanged,
+    data: {
+        entityTypeVsp,
+        entityTypeVlm,
+        roleOwner,
+        roleContributor,
+        roleViewer,
+        procedureNetwork,
+        procedureManual,
+        recentlyUpdated,
+        byVendorView,
+        itemsType
+    },
+    activeTab
+}) => (
+    <div className="catalog-filter">
+        {activeTab === onboardTabsMapping.CATALOG && (
+            <Input
+                type="select"
+                className="catalog-filter-items-type"
+                data-test-id="catalog-filter-items-type"
+                disabled={byVendorView}
+                value={itemsType}
+                onChange={e => onDataChanged({ itemsType: e.target.value })}>
+                <option
+                    key={itemsTypeConstants.ACTIVE}
+                    value={itemsTypeConstants.ACTIVE}>
+                    Active Items
+                </option>
+                <option
+                    key={itemsTypeConstants.ARCHIVED}
+                    value={itemsTypeConstants.ARCHIVED}>
+                    Archived Items
+                </option>
+            </Input>
+        )}
+        {activeTab === onboardTabsMapping.CATALOG && (
+            <Input
+                label={i18n('By Vendor View')}
+                type="checkbox"
+                disabled={itemsType === itemsTypeConstants.ARCHIVED}
+                checked={byVendorView}
+                onChange={byVendorView => onDataChanged({ byVendorView })}
+                data-test-id="filter-by-vendor-view"
+                value=""
+            />
+        )}
+        <Input
+            label={i18n('Recently Updated')}
+            type="checkbox"
+            checked={recentlyUpdated}
+            onChange={recentlyUpdated => onDataChanged({ recentlyUpdated })}
+            data-test-id="filter-recently-updated"
+            value=""
+        />
 
-               <Accordion title={i18n('ENTITY TYPE')}>
-                       <Input label={i18n('VSP')} type='checkbox' checked={entityTypeVsp} onChange={entityTypeVsp => onDataChanged({entityTypeVsp})} data-test-id='filter-type-vsp' value='' />
-                       <Input label={i18n('VLM')} type='checkbox' checked={entityTypeVlm} onChange={entityTypeVlm => onDataChanged({entityTypeVlm})} data-test-id='filter-type-vlm' value='' />                        
-               </Accordion>
+        <Accordion title={i18n('ENTITY TYPE')}>
+            <Input
+                label={i18n('VSP')}
+                type="checkbox"
+                checked={entityTypeVsp}
+                onChange={entityTypeVsp => onDataChanged({ entityTypeVsp })}
+                data-test-id="filter-type-vsp"
+                value=""
+            />
+            <Input
+                label={i18n('VLM')}
+                type="checkbox"
+                checked={entityTypeVlm}
+                onChange={entityTypeVlm => onDataChanged({ entityTypeVlm })}
+                data-test-id="filter-type-vlm"
+                value=""
+            />
+        </Accordion>
 
-               <Accordion title={i18n('ROLE')}>
-                       <Input label={i18n('Owner')} type='checkbox' checked={roleOwner} onChange={roleOwner => onDataChanged({roleOwner})}  data-test-id='filter-role-owner' value='' />
-                       <Input label={i18n('Contributer')} type='checkbox' checked={roleContributor} 
-                               onChange={roleContributor => onDataChanged({roleContributor})}  data-test-id='filter-role-contributor' value='' />
-                       <Input label={i18n('Viewer')} type='checkbox' checked={roleViewer} onChange={roleViewer => onDataChanged({roleViewer})} data-test-id='filter-role-viewr' value='' />
-               </Accordion>
-               
-               <Accordion title={i18n('ONBOARDING PROCEDURE')}>
-                       <Input label={i18n('Network Package')} type='checkbox' checked={procedureNetwork} 
-                               onChange={procedureNetwork => onDataChanged({procedureNetwork})}  data-test-id='filter-procedure-network' value='' />
-                       <Input label={i18n('Manual')} type='checkbox' checked={procedureManual} 
-                               onChange={procedureManual => onDataChanged({procedureManual})} data-test-id='filter-procedure-manual' value='' />                       
-               </Accordion>
+        <Accordion title={i18n('ROLE')}>
+            <Input
+                label={i18n('Owner')}
+                type="checkbox"
+                checked={roleOwner}
+                onChange={roleOwner => onDataChanged({ roleOwner })}
+                data-test-id="filter-role-owner"
+                value=""
+            />
+            <Input
+                label={i18n('Contributer')}
+                type="checkbox"
+                checked={roleContributor}
+                onChange={roleContributor => onDataChanged({ roleContributor })}
+                data-test-id="filter-role-contributor"
+                value=""
+            />
+            <Input
+                label={i18n('Viewer')}
+                type="checkbox"
+                checked={roleViewer}
+                onChange={roleViewer => onDataChanged({ roleViewer })}
+                data-test-id="filter-role-viewr"
+                value=""
+            />
+        </Accordion>
+
+        <Accordion title={i18n('ONBOARDING PROCEDURE')}>
+            <Input
+                label={i18n('Network Package')}
+                type="checkbox"
+                checked={procedureNetwork}
+                onChange={procedureNetwork =>
+                    onDataChanged({ procedureNetwork })
+                }
+                data-test-id="filter-procedure-network"
+                value=""
+            />
+            <Input
+                label={i18n('Manual')}
+                type="checkbox"
+                checked={procedureManual}
+                onChange={procedureManual => onDataChanged({ procedureManual })}
+                data-test-id="filter-procedure-manual"
+                value=""
+            />
+        </Accordion>
     </div>
 );
 
 Filter.PropTypes = {
-       onDataChanged: PropTypes.func,
-       data: PropTypes.object
+    onDataChanged: PropTypes.func,
+    data: PropTypes.object
 };
 
-export default featureToggle(featureToggleNames.FILTER)(connect(mapStateToProps, mapActionsToProps)(Filter));
+export default featureToggle(featureToggleNames.FILTER)(
+    connect(mapStateToProps, mapActionsToProps)(Filter)
+);
index d944cb0..edfe592 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       FILTER_DATA_CHANGED: null
+    FILTER_DATA_CHANGED: null
 });
 
 export const itemsType = {
-       ACTIVE: '1',
-       ARCHIVED: '2'
-};
\ No newline at end of file
+    ACTIVE: '1',
+    ARCHIVED: '2'
+};
index 963226c..f1e8574 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {actionTypes} from './FilterConstants.js';
+import { actionTypes } from './FilterConstants.js';
 
-export default (state = {}, action) => {       
-       switch (action.type) {
-               case actionTypes.FILTER_DATA_CHANGED:                                           
-                       return {                                
-                               ...state,
-                               ...action.deltaData
-                       };                      
-               default:
-                       return state;
-       }       
+export default (state = {}, action) => {
+    switch (action.type) {
+        case actionTypes.FILTER_DATA_CHANGED:
+            return {
+                ...state,
+                ...action.deltaData
+            };
+        default:
+            return state;
+    }
 };
index a85c79e..aebb829 100644 (file)
  */
 import React from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes} from './OnboardingCatalogConstants.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes } from './OnboardingCatalogConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import OnboardActionHelper from '../OnboardActionHelper.js';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 
-
 function getMessageForMigration(name) {
-       return (
-               <div>
-                       <div>{i18n('{name} needs to be updated. Click ‘Checkout & Update’, to proceed.', {name: name})}</div>
-                       <div>{i18n('Please don’t forget to submit afterwards')}</div>
-               </div>
-       );
+    return (
+        <div>
+            <div>
+                {i18n(
+                    '{name} needs to be updated. Click ‘Checkout & Update’, to proceed.',
+                    { name: name }
+                )}
+            </div>
+            <div>{i18n('Please don’t forget to submit afterwards')}</div>
+        </div>
+    );
 }
 
 const OnboardingCatalogActionHelper = {
-       changeVspOverlay(dispatch, vendor) {
-               dispatch({
-                       type: actionTypes.CHANGE_VSP_OVERLAY,
-                       vendorId: vendor ? vendor.id : null
-               });
-       },
-       closeVspOverlay(dispatch) {
-               dispatch({
-                       type: actionTypes.CLOSE_VSP_OVERLAY
-               });
-       },
-       changeActiveTab(dispatch, activeTab) {
-               OnboardActionHelper.clearSearchValue(dispatch);
-               dispatch({
-                       type: actionTypes.CHANGE_ACTIVE_CATALOG_TAB,
-                       activeTab
-               });
-       },
-       onVendorSelect(dispatch, {vendor}) {
-               OnboardActionHelper.clearSearchValue(dispatch);
-               dispatch({
-                       type: actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE,
-                       selectedVendor: vendor
-               });
-       },
-       onMigrate(dispatch, softwareProduct) {
-               const {name, lockingUser} = softwareProduct;
-               if (NaN === NaN) { // TODO
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                               data: {
-                                       title: 'WARNING',
-                                       msg: i18n('{name} is locked by user {lockingUser} for self-healing', {name: name, lockingUser: lockingUser})
-                               }
-                       });
-               } else {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                               data:{
-                                       title: 'WARNING',
-                                       msg: getMessageForMigration(softwareProduct.name.toUpperCase()),
-                                       confirmationButtonText: i18n('Checkout & Update'),
-                                       onConfirmed: ()=>SoftwareProductActionHelper.migrateSoftwareProduct(dispatch, {softwareProduct})
-                               }
-                       });
-               }
-       }
+    changeVspOverlay(dispatch, vendor) {
+        dispatch({
+            type: actionTypes.CHANGE_VSP_OVERLAY,
+            vendorId: vendor ? vendor.id : null
+        });
+    },
+    closeVspOverlay(dispatch) {
+        dispatch({
+            type: actionTypes.CLOSE_VSP_OVERLAY
+        });
+    },
+    changeActiveTab(dispatch, activeTab) {
+        OnboardActionHelper.clearSearchValue(dispatch);
+        dispatch({
+            type: actionTypes.CHANGE_ACTIVE_CATALOG_TAB,
+            activeTab
+        });
+    },
+    onVendorSelect(dispatch, { vendor }) {
+        OnboardActionHelper.clearSearchValue(dispatch);
+        dispatch({
+            type: actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE,
+            selectedVendor: vendor
+        });
+    },
+    onMigrate(dispatch, softwareProduct) {
+        const { name, lockingUser } = softwareProduct;
+        if (NaN === NaN) {
+            // TODO
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    title: 'WARNING',
+                    msg: i18n(
+                        '{name} is locked by user {lockingUser} for self-healing',
+                        {
+                            name: name,
+                            lockingUser: lockingUser
+                        }
+                    )
+                }
+            });
+        } else {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    title: 'WARNING',
+                    msg: getMessageForMigration(
+                        softwareProduct.name.toUpperCase()
+                    ),
+                    confirmationButtonText: i18n('Checkout & Update'),
+                    onConfirmed: () =>
+                        SoftwareProductActionHelper.migrateSoftwareProduct(
+                            dispatch,
+                            {
+                                softwareProduct
+                            }
+                        )
+                }
+            });
+        }
+    }
 };
 
 export default OnboardingCatalogActionHelper;
index 239ae45..f0cefdc 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const catalogItemTypes = Object.freeze({
-       LICENSE_MODEL: 'license-model',
-       SOFTWARE_PRODUCT: 'software-product'
+    LICENSE_MODEL: 'license-model',
+    SOFTWARE_PRODUCT: 'software-product'
 });
 
 export const catalogItemTypeClasses = {
-       LICENSE_MODEL: 'license-model-type',
-       SOFTWARE_PRODUCT: 'software-product-type',
-       VENDOR: 'vendor-type'
+    LICENSE_MODEL: 'license-model-type',
+    SOFTWARE_PRODUCT: 'software-product-type',
+    VENDOR: 'vendor-type'
 };
 
 export const catalogItemStatuses = {
-       DRAFT: 'Draft',
-       CERTIFIED: 'Certified',
-       ARCHIVED: 'ARCHIVED'
+    DRAFT: 'Draft',
+    CERTIFIED: 'Certified',
+    ARCHIVED: 'ARCHIVED'
 };
 
 export const modalMapper = {
-       'license-model': 'LICENSE_MODEL',
-       'software-product': 'SOFTWARE_PRODUCT'
+    'license-model': 'LICENSE_MODEL',
+    'software-product': 'SOFTWARE_PRODUCT'
 };
 
 export const tabsMapping = {
-       'BY_VENDOR': 1,
-       'ACTIVE': 2,
-       'ARCHIVE': 3
+    BY_VENDOR: 1,
+    ACTIVE: 2,
+    ARCHIVE: 3
 };
 
 export const migrationStatusMapper = {
-       OLD_VERSION: 'True',
+    OLD_VERSION: 'True'
 };
 
 export const actionTypes = keyMirror({
-       ONBOARDING_CATALOG_OPEN_VENDOR_PAGE: null,
-       CHANGE_ACTIVE_CATALOG_TAB: null,
-       CHANGE_SEARCH_VALUE: null,
-       CHANGE_VSP_OVERLAY: null,
-       CLOSE_VSP_OVERLAY: null
+    ONBOARDING_CATALOG_OPEN_VENDOR_PAGE: null,
+    CHANGE_ACTIVE_CATALOG_TAB: null,
+    CHANGE_SEARCH_VALUE: null,
+    CHANGE_VSP_OVERLAY: null,
+    CLOSE_VSP_OVERLAY: null
 });
index 3f8a833..9796cf8 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {actionTypes, tabsMapping} from './OnboardingCatalogConstants.js';
-import {combineReducers} from 'redux';
+import { actionTypes, tabsMapping } from './OnboardingCatalogConstants.js';
+import { combineReducers } from 'redux';
 import vendorCatalogReducer from './VendorCatalogReducer.js';
 
 const onboardingCatalogReducer = combineReducers({
-       vendorCatalog: vendorCatalogReducer,
-       activeTab: (state = tabsMapping.ACTIVE, action) => action.type === actionTypes.CHANGE_ACTIVE_CATALOG_TAB ? action.activeTab : state
+    vendorCatalog: vendorCatalogReducer,
+    activeTab: (state = tabsMapping.ACTIVE, action) =>
+        action.type === actionTypes.CHANGE_ACTIVE_CATALOG_TAB
+            ? action.activeTab
+            : state
 });
 
 export default (state, action) => {
-       if (action.type === actionTypes.RESET_ONBOARDING_CATALOG_STORE) {
-               state = undefined;
-       }
-       return onboardingCatalogReducer(state, action);
+    if (action.type === actionTypes.RESET_ONBOARDING_CATALOG_STORE) {
+        state = undefined;
+    }
+    return onboardingCatalogReducer(state, action);
 };
index 7825825..d1e401f 100644 (file)
@@ -14,6 +14,8 @@
  * permissions and limitations under the License.
  */
 
-export const filterCatalogItemsByType = ({items, filter}) => {
-       return items.filter(item => item.name.toLowerCase().indexOf(filter.toLowerCase()) > -1);
+export const filterCatalogItemsByType = ({ items, filter }) => {
+    return items.filter(
+        item => item.name.toLowerCase().indexOf(filter.toLowerCase()) > -1
+    );
 };
index 8ae8549..2cc32c2 100644 (file)
@@ -18,120 +18,202 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import classnames from 'classnames';
 import DetailsCatalogView from 'sdc-app/onboarding/onboard/DetailsCatalogView.jsx';
 import VendorCatalogView from './VendorCatalogView.jsx';
-import { tabsMapping} from './OnboardingCatalogConstants.js';
-import {tabsMapping as WCTabsMapping} from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+import { tabsMapping } from './OnboardingCatalogConstants.js';
+import { tabsMapping as WCTabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
 import featureToggle from 'sdc-app/features/featureToggle.js';
-import {featureToggleNames} from 'sdc-app/features/FeaturesConstants.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 
-const Separator = () => (
-       <div className='tab-separator'/>
-);
+const Separator = () => <div className="tab-separator" />;
 
-const Tab = ({onTabPress, title, dataTestId, activeTab, tabMapping}) => (
-       <div
-               className={classnames('catalog-header-tab', {'active': activeTab === tabMapping })}
-               onClick={() => onTabPress(tabMapping)}
-               data-test-id={dataTestId}>
-               {title}
-       </div>
+const Tab = ({ onTabPress, title, dataTestId, activeTab, tabMapping }) => (
+    <div
+        className={classnames('catalog-header-tab', {
+            active: activeTab === tabMapping
+        })}
+        onClick={() => onTabPress(tabMapping)}
+        data-test-id={dataTestId}>
+        {title}
+    </div>
 );
 
 const ArchiveTab = featureToggle(featureToggleNames.ARCHIVE_ITEM)(Tab);
-const ArchiveTabSeparator = featureToggle(featureToggleNames.ARCHIVE_ITEM)(Separator);
+const ArchiveTabSeparator = featureToggle(featureToggleNames.ARCHIVE_ITEM)(
+    Separator
+);
 
-const CatalogHeaderTabs = (props) => (
-       <div className='catalog-header-tabs'>
-               <Tab {...props} title={i18n('ACTIVE')}  dataTestId='catalog-all-tab' tabMapping={tabsMapping.ACTIVE}/>
-               <Separator/>
-               <Tab {...props} title={i18n('BY VENDOR')} dataTestId='catalog-header-tab' tabMapping={tabsMapping.BY_VENDOR}/>
-               <ArchiveTabSeparator/>
-               <ArchiveTab {...props} title={i18n('ARCHIVE')} dataTestId='catalog-archive-tab' tabMapping={tabsMapping.ARCHIVE}/>
-       </div>
+const CatalogHeaderTabs = props => (
+    <div className="catalog-header-tabs">
+        <Tab
+            {...props}
+            title={i18n('ACTIVE')}
+            dataTestId="catalog-all-tab"
+            tabMapping={tabsMapping.ACTIVE}
+        />
+        <Separator />
+        <Tab
+            {...props}
+            title={i18n('BY VENDOR')}
+            dataTestId="catalog-header-tab"
+            tabMapping={tabsMapping.BY_VENDOR}
+        />
+        <ArchiveTabSeparator />
+        <ArchiveTab
+            {...props}
+            title={i18n('ARCHIVE')}
+            dataTestId="catalog-archive-tab"
+            tabMapping={tabsMapping.ARCHIVE}
+        />
+    </div>
 );
 
-const CatalogHeader = ({activeTab, onTabPress}) => (
-       <div className='catalog-header'>
-               <CatalogHeaderTabs activeTab={activeTab} onTabPress={onTabPress} />
-       </div>
+const CatalogHeader = ({ activeTab, onTabPress }) => (
+    <div className="catalog-header">
+        <CatalogHeaderTabs activeTab={activeTab} onTabPress={onTabPress} />
+    </div>
 );
 
 const FilterCatalogHeader = () => (
-       <div className='catalog-header'>
-               <div className='catalog-header-tabs'>
-                       <div className='catalog-header-tab active'>
-                               {i18n('ONBOARD CATALOG')}
-                       </div>
-               </div>  
-       </div>
+    <div className="catalog-header">
+        <div className="catalog-header-tabs">
+            <div className="catalog-header-tab active">
+                {i18n('ONBOARD CATALOG')}
+            </div>
+        </div>
+    </div>
 );
 
-
-const FeaturedCatalogHeader = featureToggle(featureToggleNames.FILTER)({AComp: FilterCatalogHeader, BComp: CatalogHeader});
+const FeaturedCatalogHeader = featureToggle(featureToggleNames.FILTER)({
+    AComp: FilterCatalogHeader,
+    BComp: CatalogHeader
+});
 
 class OnboardingCatalogView extends React.Component {
-       renderViewByTab(activeTab){
-               const {finalizedLicenseModelList: licenseModelList, fullLicenseModelList, users, vspOverlay, finalizedSoftwareProductList: softwareProductList, onSelectLicenseModel, onSelectSoftwareProduct,
-                               onAddLicenseModelClick, onAddSoftwareProductClick, onVspOverlayChange, onVendorSelect, selectedVendor, searchValue, onMigrate,
-                               archivedSoftwareProductList, archivedLicenseModelList} = this.props;
+    renderViewByTab(activeTab) {
+        const {
+            finalizedLicenseModelList: licenseModelList,
+            fullLicenseModelList,
+            users,
+            vspOverlay,
+            finalizedSoftwareProductList: softwareProductList,
+            onSelectLicenseModel,
+            onSelectSoftwareProduct,
+            onAddLicenseModelClick,
+            onAddSoftwareProductClick,
+            onVspOverlayChange,
+            onVendorSelect,
+            selectedVendor,
+            searchValue,
+            onMigrate,
+            archivedSoftwareProductList,
+            archivedLicenseModelList
+        } = this.props;
 
-               switch (activeTab){
-                       case tabsMapping.ARCHIVE:
-                               return (
-                                       <DetailsCatalogView
-                                               VLMList={archivedLicenseModelList}
-                                               VSPList={archivedSoftwareProductList}
-                                               users={users}                                           
-                                               onSelectVLM={(item, users) => onSelectLicenseModel(item, users, WCTabsMapping.CATALOG)}
-                                               onSelectVSP={(item, users) => onSelectSoftwareProduct(item, users, WCTabsMapping.CATALOG)}
-                                               filter={searchValue}
-                                               onMigrate={onMigrate}/>
-                               );
-                       case tabsMapping.ACTIVE:
-                               return (
-                                       <DetailsCatalogView
-                                               VLMList={licenseModelList}
-                                               VSPList={softwareProductList}
-                                               users={users}
-                                               onAddVLM={onAddLicenseModelClick}
-                                               onAddVSP={onAddSoftwareProductClick}
-                                               onSelectVLM={(item, users) => onSelectLicenseModel(item, users, WCTabsMapping.CATALOG)}
-                                               onSelectVSP={(item, users) => onSelectSoftwareProduct(item, users, WCTabsMapping.CATALOG)}
-                                               filter={searchValue}
-                                               onMigrate={onMigrate}/>
-                               );
-                       case tabsMapping.BY_VENDOR:
-                       default:
-                               return (
-                                       <VendorCatalogView
-                                               licenseModelList={fullLicenseModelList}
-                                               users={users}
-                                               onAddVSP={onAddSoftwareProductClick}
-                                               onAddVLM={onAddLicenseModelClick}
-                                               onSelectVSP={(item, users) => onSelectSoftwareProduct(item, users, WCTabsMapping.CATALOG)}
-                                               onSelectVLM={(item, users) => onSelectLicenseModel(item, users, WCTabsMapping.CATALOG)}
-                                               vspOverlay={vspOverlay}
-                                               onVendorSelect={onVendorSelect}
-                                               selectedVendor={selectedVendor}
-                                               onVspOverlayChange={onVspOverlayChange}
-                                               onMigrate={onMigrate}
-                                               filter={searchValue}/>
-                               );
-               }
-       }
+        switch (activeTab) {
+            case tabsMapping.ARCHIVE:
+                return (
+                    <DetailsCatalogView
+                        VLMList={archivedLicenseModelList}
+                        VSPList={archivedSoftwareProductList}
+                        users={users}
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        filter={searchValue}
+                        onMigrate={onMigrate}
+                    />
+                );
+            case tabsMapping.ACTIVE:
+                return (
+                    <DetailsCatalogView
+                        VLMList={licenseModelList}
+                        VSPList={softwareProductList}
+                        users={users}
+                        onAddVLM={onAddLicenseModelClick}
+                        onAddVSP={onAddSoftwareProductClick}
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        filter={searchValue}
+                        onMigrate={onMigrate}
+                    />
+                );
+            case tabsMapping.BY_VENDOR:
+            default:
+                return (
+                    <VendorCatalogView
+                        licenseModelList={fullLicenseModelList}
+                        users={users}
+                        onAddVSP={onAddSoftwareProductClick}
+                        onAddVLM={onAddLicenseModelClick}
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        vspOverlay={vspOverlay}
+                        onVendorSelect={onVendorSelect}
+                        selectedVendor={selectedVendor}
+                        onVspOverlayChange={onVspOverlayChange}
+                        onMigrate={onMigrate}
+                        filter={searchValue}
+                    />
+                );
+        }
+    }
 
-       render() {
-               const {selectedVendor, catalogActiveTab: activeTab, onCatalogTabClick, onSearch, searchValue} = this.props;
-               return (
-                       <div className='catalog-wrapper'>
-                               {!selectedVendor && <FeaturedCatalogHeader
-                                       onSearch={event => onSearch(event.target.value)}
-                                       activeTab={activeTab}
-                                       onTabPress={tab => onCatalogTabClick(tab)}
-                                       searchValue={searchValue}/>}
-                               {this.renderViewByTab(activeTab)}
-                       </div>
-               );
-       }
+    render() {
+        const {
+            selectedVendor,
+            catalogActiveTab: activeTab,
+            onCatalogTabClick,
+            onSearch,
+            searchValue
+        } = this.props;
+        return (
+            <div className="catalog-wrapper">
+                {!selectedVendor && (
+                    <FeaturedCatalogHeader
+                        onSearch={event => onSearch(event.target.value)}
+                        activeTab={activeTab}
+                        onTabPress={tab => onCatalogTabClick(tab)}
+                        searchValue={searchValue}
+                    />
+                )}
+                {this.renderViewByTab(activeTab)}
+            </div>
+        );
+    }
 }
 
 export default OnboardingCatalogView;
index 80d9b07..2f00bf9 100644 (file)
@@ -19,13 +19,27 @@ import Tooltip from 'react-bootstrap/lib/Tooltip.js';
 import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
 
 const tooltip = (msg, className = '') => (
-       <Tooltip className={className} id={className}>{msg}</Tooltip>
+    <Tooltip className={className} id={className}>
+        {msg}
+    </Tooltip>
 );
 
-export const TooltipWrapper = ({placement = 'top', className = '', tooltipClassName = '', dataTestId, delayShow = 0, children}) => (
-       <OverlayTrigger placement={placement} overlay={tooltip(children, tooltipClassName)} delayShow={delayShow}>
-               <div className={className} data-test-id={dataTestId}>{children}</div>
-       </OverlayTrigger>
+export const TooltipWrapper = ({
+    placement = 'top',
+    className = '',
+    tooltipClassName = '',
+    dataTestId,
+    delayShow = 0,
+    children
+}) => (
+    <OverlayTrigger
+        placement={placement}
+        overlay={tooltip(children, tooltipClassName)}
+        delayShow={delayShow}>
+        <div className={className} data-test-id={dataTestId}>
+            {children}
+        </div>
+    </OverlayTrigger>
 );
 
 export default tooltip;
index a2852e5..c2eb825 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {migrationStatusMapper} from './OnboardingCatalogConstants.js';
+import { migrationStatusMapper } from './OnboardingCatalogConstants.js';
 
-const VSPOverlay = ({VSPList, onSelectVSP, onSeeMore, onMigrate}) => (
-       <div className='vsp-overlay-wrapper' onClick={(e) => {
-               e.stopPropagation();
-               e.preventDefault();
-       }}>
-               <div className='vsp-overlay-arrow'></div>
-               <div className='vsp-overlay'>
-                       <div className='vsp-overlay-title'>{i18n('Recently Edited')}</div>
-                       <div className='vsp-overlay-list'>
-                               {VSPList.slice(0, 5).map(vsp => <div key={vsp.id} className='vsp-overlay-detail' onClick={() => {
-                                       if (vsp.isOldVersion && vsp.isOldVersion === migrationStatusMapper.OLD_VERSION) {
-                                               onMigrate({
-                                                       softwareProduct: vsp
-                                               });
-                                       } else {
-                                               onSelectVSP(vsp);
-                                       }
-                               }
-                               }>{i18n(vsp.name)}</div>)}
-                       </div>
-                       {VSPList.length > 5 && <div className='vsp-overlay-see-more' onClick={onSeeMore}>{i18n('See More')}</div>}
-               </div>
-       </div>
+const VSPOverlay = ({ VSPList, onSelectVSP, onSeeMore, onMigrate }) => (
+    <div
+        className="vsp-overlay-wrapper"
+        onClick={e => {
+            e.stopPropagation();
+            e.preventDefault();
+        }}>
+        <div className="vsp-overlay-arrow" />
+        <div className="vsp-overlay">
+            <div className="vsp-overlay-title">{i18n('Recently Edited')}</div>
+            <div className="vsp-overlay-list">
+                {VSPList.slice(0, 5).map(vsp => (
+                    <div
+                        key={vsp.id}
+                        className="vsp-overlay-detail"
+                        onClick={() => {
+                            if (
+                                vsp.isOldVersion &&
+                                vsp.isOldVersion ===
+                                    migrationStatusMapper.OLD_VERSION
+                            ) {
+                                onMigrate({
+                                    softwareProduct: vsp
+                                });
+                            } else {
+                                onSelectVSP(vsp);
+                            }
+                        }}>
+                        {i18n(vsp.name)}
+                    </div>
+                ))}
+            </div>
+            {VSPList.length > 5 && (
+                <div className="vsp-overlay-see-more" onClick={onSeeMore}>
+                    {i18n('See More')}
+                </div>
+            )}
+        </div>
+    </div>
 );
 
 VSPOverlay.PropTypes = {
-       VSPList: PropTypes.array,
-       onSelectVSP: PropTypes.func
+    VSPList: PropTypes.array,
+    onSelectVSP: PropTypes.func
 };
 
 export default VSPOverlay;
index dd8b41b..2d22a2d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './OnboardingCatalogConstants.js';
+import { actionTypes } from './OnboardingCatalogConstants.js';
 
 export default (state = {}, action) => {
-       switch(action.type) {
-               case actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE:
-                       return {
-                               ...state,
-                               selectedVendor: action.selectedVendor
-                       };
-               case actionTypes.CHANGE_VSP_OVERLAY:
-                       return {
-                               ...state,
-                               vspOverlay: action.vendorId
-                       };
-               case actionTypes.CLOSE_VSP_OVERLAY:
-                       return {
-                               ...state,
-                               vspOverlay: null
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE:
+            return {
+                ...state,
+                selectedVendor: action.selectedVendor
+            };
+        case actionTypes.CHANGE_VSP_OVERLAY:
+            return {
+                ...state,
+                vspOverlay: action.vendorId
+            };
+        case actionTypes.CLOSE_VSP_OVERLAY:
+            return {
+                ...state,
+                vspOverlay: null
+            };
+        default:
+            return state;
+    }
 };
index 9914ea2..02f8d50 100644 (file)
@@ -17,58 +17,100 @@ import React from 'react';
 import VendorItem from './VendorItem.jsx';
 import CatalogList from '../CatalogList.jsx';
 import CatalogItemDetails from '../CatalogItemDetails.jsx';
-import {catalogItemTypes} from './OnboardingCatalogConstants.js';
-import {filterCatalogItemsByType} from './OnboardingCatalogUtils.js';
+import { catalogItemTypes } from './OnboardingCatalogConstants.js';
+import { filterCatalogItemsByType } from './OnboardingCatalogUtils.js';
 
-const VendorList = ({onAddVLM, onAddVSP, onSelectVSP, licenseModelList = [], vspOverlay: currentOverlay, onVspOverlayChange, onVendorSelect, filter, onMigrate, users}) => {
-       return(
-               <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
-                       {
-                               filterCatalogItemsByType({items: licenseModelList, filter}).map(vlm =>
-                                       <VendorItem
-                                               key={vlm.id}
-                                               onAddVSP={onAddVSP}
-                                               onSelectVSP={(vsp) => onSelectVSP(vsp, users)}
-                                               shouldShowOverlay={currentOverlay === vlm.id}
-                                               onVSPButtonClick={(hasVSP) => onVspOverlayChange(vlm.id === currentOverlay || !hasVSP ? null : vlm)}
-                                               onVendorSelect={onVendorSelect}
-                                               onMigrate={onMigrate}
-                                               vendor={vlm}/>)
-                       }
-               </CatalogList>
-       );
+const VendorList = ({
+    onAddVLM,
+    onAddVSP,
+    onSelectVSP,
+    licenseModelList = [],
+    vspOverlay: currentOverlay,
+    onVspOverlayChange,
+    onVendorSelect,
+    filter,
+    onMigrate,
+    users
+}) => {
+    return (
+        <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+            {filterCatalogItemsByType({ items: licenseModelList, filter }).map(
+                vlm => (
+                    <VendorItem
+                        key={vlm.id}
+                        onAddVSP={onAddVSP}
+                        onSelectVSP={vsp => onSelectVSP(vsp, users)}
+                        shouldShowOverlay={currentOverlay === vlm.id}
+                        onVSPButtonClick={hasVSP =>
+                            onVspOverlayChange(
+                                vlm.id === currentOverlay || !hasVSP
+                                    ? null
+                                    : vlm
+                            )
+                        }
+                        onVendorSelect={onVendorSelect}
+                        onMigrate={onMigrate}
+                        vendor={vlm}
+                    />
+                )
+            )}
+        </CatalogList>
+    );
 };
 
-const SoftwareProductListByVendor = ({onAddVSP, selectedVendor, onVendorSelect, onSelectVSP, onSelectVLM, filter, onMigrate, users}) => {
-       return(
-               <div>
-                       <CatalogList onAddVSP={()=>{onAddVSP(selectedVendor.id);}} vendorPageOptions={{selectedVendor, onBack: () => onVendorSelect(false)}}>
-                               <CatalogItemDetails
-                                       key={selectedVendor.id}
-                                       onSelect={() => onSelectVLM(selectedVendor, users)}
-                                       catalogItemTypeClass={catalogItemTypes.LICENSE_MODEL}
-                                       onMigrate={onMigrate}
-                                       catalogItemData={selectedVendor}/>
-                               {
-                                       filterCatalogItemsByType({items: selectedVendor.softwareProductList, filter}).map(vsp =>
-                                               <CatalogItemDetails
-                                                       key={vsp.id}
-                                                       catalogItemTypeClass={catalogItemTypes.SOFTWARE_PRODUCT}
-                                                       onMigrate={onMigrate}
-                                                       onSelect={() => onSelectVSP(vsp, users)}
-                                                       catalogItemData={vsp}/>
-                                       )
-                               }
-                       </CatalogList>
-               </div>
-       );
+const SoftwareProductListByVendor = ({
+    onAddVSP,
+    selectedVendor,
+    onVendorSelect,
+    onSelectVSP,
+    onSelectVLM,
+    filter,
+    onMigrate,
+    users
+}) => {
+    return (
+        <div>
+            <CatalogList
+                onAddVSP={() => {
+                    onAddVSP(selectedVendor.id);
+                }}
+                vendorPageOptions={{
+                    selectedVendor,
+                    onBack: () => onVendorSelect(false)
+                }}>
+                <CatalogItemDetails
+                    key={selectedVendor.id}
+                    onSelect={() => onSelectVLM(selectedVendor, users)}
+                    catalogItemTypeClass={catalogItemTypes.LICENSE_MODEL}
+                    onMigrate={onMigrate}
+                    catalogItemData={selectedVendor}
+                />
+                {filterCatalogItemsByType({
+                    items: selectedVendor.softwareProductList,
+                    filter
+                }).map(vsp => (
+                    <CatalogItemDetails
+                        key={vsp.id}
+                        catalogItemTypeClass={catalogItemTypes.SOFTWARE_PRODUCT}
+                        onMigrate={onMigrate}
+                        onSelect={() => onSelectVSP(vsp, users)}
+                        catalogItemData={vsp}
+                    />
+                ))}
+            </CatalogList>
+        </div>
+    );
 };
 
 class VendorCatalogView extends React.Component {
-       render() {
-               let {selectedVendor} = this.props;
-               return( selectedVendor ? <SoftwareProductListByVendor {...this.props}/> : <VendorList {...this.props}/>);
-       }
+    render() {
+        let { selectedVendor } = this.props;
+        return selectedVendor ? (
+            <SoftwareProductListByVendor {...this.props} />
+        ) : (
+            <VendorList {...this.props} />
+        );
+    }
 }
 
 export default VendorCatalogView;
index 158282c..bef47d5 100644 (file)
 import React from 'react';
 import PropTypes from 'prop-types';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {Tile, TileInfo, TileInfoLine, TileFooter, TileFooterCell, Button} from 'sdc-ui/lib/react';
+import {
+    Tile,
+    TileInfo,
+    TileInfoLine,
+    TileFooter,
+    TileFooterCell,
+    Button
+} from 'sdc-ui/lib/react';
 
 import VSPOverlay from './VSPOverlay.jsx';
-import {TooltipWrapper} from './Tooltip.jsx';
+import { TooltipWrapper } from './Tooltip.jsx';
 
 class VendorItem extends React.Component {
+    static PropTypes = {
+        softwareProductList: PropTypes.array,
+        vendor: PropTypes.object,
+        shouldShowOverlay: PropTypes.bool,
+        onSelectVSP: PropTypes.func,
+        onVendorSelect: PropTypes.func,
+        onAddVSP: PropTypes.func,
+        onVSPButtonClick: PropTypes.func
+    };
 
-       static PropTypes = {
-               softwareProductList: PropTypes.array,
-               vendor: PropTypes.object,
-               shouldShowOverlay: PropTypes.bool,
-               onSelectVSP: PropTypes.func,
-               onVendorSelect: PropTypes.func,
-               onAddVSP: PropTypes.func,
-               onVSPButtonClick: PropTypes.func
-       };
+    render() {
+        let {
+            vendor,
+            onSelectVSP,
+            shouldShowOverlay,
+            onVendorSelect,
+            onMigrate
+        } = this.props;
+        let { softwareProductList = [], name } = vendor;
+        return (
+            <Tile iconName="vendor" onClick={() => onVendorSelect(vendor)}>
+                <TileInfo align="center">
+                    <TileInfoLine type="title">
+                        <TooltipWrapper
+                            className="with-overlay"
+                            dataTestId="catalog-item-name">
+                            {name}
+                        </TooltipWrapper>
+                    </TileInfoLine>
+                    <TileInfoLine>
+                        <Button
+                            btnType="outline-rounded"
+                            color="dark-gray"
+                            onClick={e => this.handleVspCountClick(e)}
+                            data-test-id="catalog-vsp-count"
+                            disabled={!softwareProductList.length}>
+                            {i18n('{length} VSPs', {
+                                length: softwareProductList.length
+                            })}
+                        </Button>
+                        {shouldShowOverlay &&
+                            softwareProductList.length > 0 && (
+                                <VSPOverlay
+                                    onMigrate={onMigrate}
+                                    VSPList={softwareProductList}
+                                    onSelectVSP={onSelectVSP}
+                                    onSeeMore={() => onVendorSelect(vendor)}
+                                />
+                            )}
+                    </TileInfoLine>
+                </TileInfo>
+                <TileFooter align="center">
+                    <TileFooterCell dataTestId="catalog-create-new-vsp-from-vendor">
+                        <Button
+                            btnType="link"
+                            color="primary"
+                            iconName="plusThin"
+                            onClick={e => this.onCreateVspClick(e)}>
+                            {i18n('Create new VSP')}
+                        </Button>
+                    </TileFooterCell>
+                </TileFooter>
+            </Tile>
+        );
+    }
 
-       render() {
-               let {vendor, onSelectVSP, shouldShowOverlay, onVendorSelect, onMigrate} = this.props;
-               let {softwareProductList = [], name} = vendor;
-               return (
-                       <Tile
-                               iconName='vendor'
-                               onClick={() => onVendorSelect(vendor)}>
-                               <TileInfo align='center'>
-                                       <TileInfoLine type='title'>
-                                               <TooltipWrapper className='with-overlay' dataTestId='catalog-item-name'>{name}</TooltipWrapper>
-                                       </TileInfoLine>
-                                       <TileInfoLine>
-                                               <Button
-                                                       btnType='outline-rounded'
-                                                       color='dark-gray'
-                                                       onClick={e => this.handleVspCountClick(e)}
-                                                       data-test-id='catalog-vsp-count'
-                                                       disabled={!softwareProductList.length}>
-                                                       {i18n('{length} VSPs', {length: softwareProductList.length})}
-                                               </Button>
-                                               {shouldShowOverlay && softwareProductList.length > 0 &&
-                                                       <VSPOverlay
-                                                               onMigrate={onMigrate}
-                                                               VSPList={softwareProductList}
-                                                               onSelectVSP={onSelectVSP}
-                                                               onSeeMore={() => onVendorSelect(vendor)} />
-                                               }
-                                       </TileInfoLine>
-                               </TileInfo>
-                               <TileFooter align='center'>
-                                       <TileFooterCell dataTestId='catalog-create-new-vsp-from-vendor'>
-                                               <Button
-                                                       btnType='link'
-                                                       color='primary'
-                                                       iconName='plusThin'
-                                                       onClick={e => this.onCreateVspClick(e)}>
-                                                       {i18n('Create new VSP')}
-                                               </Button>
-                                       </TileFooterCell>
-                               </TileFooter>
-                       </Tile>
-               );
-       }
-
-       onCreateVspClick(e) {
-               e.stopPropagation();
-               e.preventDefault();
-               const {onAddVSP, vendor: {id}} = this.props;
-               onAddVSP(id);
-       }
-
-       handleVspCountClick(e){
-               e.stopPropagation();
-               e.preventDefault();
-               const {onVSPButtonClick, vendor: {softwareProductList}} = this.props;
-               const hasVSP = Boolean(softwareProductList.length);
-               onVSPButtonClick(hasVSP);
-       }
+    onCreateVspClick(e) {
+        e.stopPropagation();
+        e.preventDefault();
+        const { onAddVSP, vendor: { id } } = this.props;
+        onAddVSP(id);
+    }
 
+    handleVspCountClick(e) {
+        e.stopPropagation();
+        e.preventDefault();
+        const {
+            onVSPButtonClick,
+            vendor: { softwareProductList }
+        } = this.props;
+        const hasVSP = Boolean(softwareProductList.length);
+        onVSPButtonClick(hasVSP);
+    }
 }
 
 export default VendorItem;
index a937c11..2f17867 100644 (file)
 import React from 'react';
 import DetailsCatalogView from '../DetailsCatalogView.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {tabsMapping} from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+import { tabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
 
-const WorkspaceView = (props) => {
-       let {
-               licenseModelList, softwareProductList, onAddLicenseModelClick, users,
-               onAddSoftwareProductClick, onSelectLicenseModel, onSelectSoftwareProduct, searchValue, onMigrate
-       } = props;
+const WorkspaceView = props => {
+    let {
+        licenseModelList,
+        softwareProductList,
+        onAddLicenseModelClick,
+        users,
+        onAddSoftwareProductClick,
+        onSelectLicenseModel,
+        onSelectSoftwareProduct,
+        searchValue,
+        onMigrate
+    } = props;
 
-       return (
-               <div className='catalog-wrapper workspace-view'>
-                       <div className='catalog-header workspace-header'>
-                               {i18n('WORKSPACE')}
-                       </div>
-                       <DetailsCatalogView
-                               VLMList={licenseModelList}
-                               VSPList={softwareProductList}
-                               users={users}
-                               onAddVLM={onAddLicenseModelClick}
-                               onAddVSP={onAddSoftwareProductClick}
-                               onSelectVLM={(item, users) => onSelectLicenseModel(item, users, tabsMapping.WORKSPACE)}
-                               onSelectVSP={(item, users) => onSelectSoftwareProduct(item, users, tabsMapping.WORKSPACE)}
-                               onMigrate={onMigrate}
-                               filter={searchValue} />
-               </div>
-       );
+    return (
+        <div className="catalog-wrapper workspace-view">
+            <div className="catalog-header workspace-header">
+                {i18n('WORKSPACE')}
+            </div>
+            <DetailsCatalogView
+                VLMList={licenseModelList}
+                VSPList={softwareProductList}
+                users={users}
+                onAddVLM={onAddLicenseModelClick}
+                onAddVSP={onAddSoftwareProductClick}
+                onSelectVLM={(item, users) =>
+                    onSelectLicenseModel(item, users, tabsMapping.WORKSPACE)
+                }
+                onSelectVSP={(item, users) =>
+                    onSelectSoftwareProduct(item, users, tabsMapping.WORKSPACE)
+                }
+                onMigrate={onMigrate}
+                filter={searchValue}
+            />
+        </div>
+    );
 };
 
 export default WorkspaceView;
index c25d93f..d42a2f8 100644 (file)
  */
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {actionTypes} from './PermissionsConstants.js';
-import {permissionTypes} from './PermissionsConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {askForRightsMsg} from './PermissionsManager.jsx';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes } from './PermissionsConstants.js';
+import { permissionTypes } from './PermissionsConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { askForRightsMsg } from './PermissionsManager.jsx';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 
 const PermissionsActionHelper = {
-       openPermissonsManager(dispatch, {itemId, askForRights}) {
-               if (askForRights) {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                               data: {
-                                       title: i18n('Ask For Contributers Rights'),
-                                       msg: askForRightsMsg(),
-                                       confirmationButtonText: i18n('SEND'),
-                                       onConfirmed: () =>      this.askForContributorRights()
-                               }
-                       });
-               } else {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                               data: {
-                                       modalComponentName: modalContentMapper.MANAGE_PERMISSIONS,
-                                       title: i18n('Manage Permissions'),
-                                       modalComponentProps: {
-                                               itemId
-                                       }
-                               }
-                       });
-               }
-       },
+    openPermissonsManager(dispatch, { itemId, askForRights }) {
+        if (askForRights) {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    title: i18n('Ask For Contributers Rights'),
+                    msg: askForRightsMsg(),
+                    confirmationButtonText: i18n('SEND'),
+                    onConfirmed: () => this.askForContributorRights()
+                }
+            });
+        } else {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.MANAGE_PERMISSIONS,
+                    title: i18n('Manage Permissions'),
+                    modalComponentProps: {
+                        itemId
+                    }
+                }
+            });
+        }
+    },
 
-       closePermissionManager(dispatch) {
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-       },
+    closePermissionManager(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+    },
 
-       saveItemUsers(dispatch, {itemId, removedUsersIds, addedUsersIds, allUsers}) {
-               return ItemsHelper.updateContributors({itemId, removedUsersIds, addedUsersIds}).then(() =>
-                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers})
-               );
-       },
+    saveItemUsers(
+        dispatch,
+        { itemId, removedUsersIds, addedUsersIds, allUsers }
+    ) {
+        return ItemsHelper.updateContributors({
+            itemId,
+            removedUsersIds,
+            addedUsersIds
+        }).then(() =>
+            PermissionsActionHelper.fetchItemUsers(dispatch, {
+                itemId,
+                allUsers
+            })
+        );
+    },
 
-       changeOwner(dispatch, {itemId, newOwnerId, allUsers}) {
-               return ItemsHelper.changeOwner({itemId, ownerId: newOwnerId}).then(() =>
-                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers})
-               );
-       },
+    changeOwner(dispatch, { itemId, newOwnerId, allUsers }) {
+        return ItemsHelper.changeOwner({ itemId, ownerId: newOwnerId }).then(
+            () =>
+                PermissionsActionHelper.fetchItemUsers(dispatch, {
+                    itemId,
+                    allUsers
+                })
+        );
+    },
 
-       fetchItemUsers(dispatch, {itemId, allUsers}) {
-               return ItemsHelper.fetchUsers({itemId}).then(response => {
+    fetchItemUsers(dispatch, { itemId, allUsers }) {
+        return ItemsHelper.fetchUsers({ itemId }).then(response => {
+            let allContributors = response.results;
 
-                       let allContributors = response.results;
-
-                       let owner = {};
-                       let contributors = [];
-                       allContributors.map(user => {
-                               let userObject = allUsers.find(userObject => userObject.userId === user.userId);
-                               if (userObject) {
-                                       user = {...user, fullName: userObject.fullName, role: userObject.role};
-
-                                       switch(user.permission) {
-                                               case permissionTypes.OWNER:
-                                                       owner = user;
-                                                       break;
-                                               case permissionTypes.CONTRIBUTOR:
-                                                       contributors.push(user);
-                                                       break;
-                                       }
-                               }
-                       });
-
-                       dispatch({
-                               type: actionTypes.ITEM_USERS_LOADED,
-                               contributors,
-                               owner
-                       });
-               });
-       },
-
-       askForContributorRights() {
-               console.log('asked for contributor rights');
-       }
+            let owner = {};
+            let contributors = [];
+            allContributors.map(user => {
+                let userObject = allUsers.find(
+                    userObject => userObject.userId === user.userId
+                );
+                if (userObject) {
+                    user = {
+                        ...user,
+                        fullName: userObject.fullName,
+                        role: userObject.role
+                    };
 
+                    switch (user.permission) {
+                        case permissionTypes.OWNER:
+                            owner = user;
+                            break;
+                        case permissionTypes.CONTRIBUTOR:
+                            contributors.push(user);
+                            break;
+                    }
+                }
+            });
 
+            dispatch({
+                type: actionTypes.ITEM_USERS_LOADED,
+                contributors,
+                owner
+            });
+        });
+    },
 
+    askForContributorRights() {
+        console.log('asked for contributor rights');
+    }
 };
 
 export default PermissionsActionHelper;
index 48a3461..686aaaf 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       ITEM_USERS_LOADED: null
+    ITEM_USERS_LOADED: null
 });
 
 export const permissionTypes = {
-       OWNER: 'Owner',
-       CONTRIBUTOR: 'Contributor'
+    OWNER: 'Owner',
+    CONTRIBUTOR: 'Contributor'
 };
 
-export const changeOwnerMessage = 'You will no longer be able to manage the permissions of this item.\nYour permission level will be set to contributor.';
+export const changeOwnerMessage =
+    'You will no longer be able to manage the permissions of this item.\nYour permission level will be set to contributor.';
index ba6562b..3b6d62b 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import PermissionsManager from './PermissionsManager.jsx';
 import PermissionsActionHelper from './PermissionsActionHelper.js';
 
-export const mapStateToProps = ({versionsPage, users: {usersList, userInfo}}) => {
-       let {permissions} = versionsPage;
+export const mapStateToProps = ({
+    versionsPage,
+    users: { usersList, userInfo }
+}) => {
+    let { permissions } = versionsPage;
 
-       return {
-               users: usersList,
-               userInfo,
-               owner: permissions.owner,
-               itemUsers: permissions.contributors
-       };
+    return {
+        users: usersList,
+        userInfo,
+        owner: permissions.owner,
+        itemUsers: permissions.contributors
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               onCancel: () => PermissionsActionHelper.closePermissionManager(dispatch),
-               onSubmit: ({itemId, addedUsersIds, removedUsersIds, allUsers, newOwnerId}) => {
-                       return PermissionsActionHelper.saveItemUsers(dispatch,{itemId, addedUsersIds, removedUsersIds, allUsers}).then(() => {
-                               return newOwnerId ? PermissionsActionHelper.changeOwner(dispatch, {itemId, newOwnerId, allUsers}) : Promise.resolve();
-                       }).then(() => PermissionsActionHelper.closePermissionManager(dispatch));
-               }
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        onCancel: () =>
+            PermissionsActionHelper.closePermissionManager(dispatch),
+        onSubmit: ({
+            itemId,
+            addedUsersIds,
+            removedUsersIds,
+            allUsers,
+            newOwnerId
+        }) => {
+            return PermissionsActionHelper.saveItemUsers(dispatch, {
+                itemId,
+                addedUsersIds,
+                removedUsersIds,
+                allUsers
+            })
+                .then(() => {
+                    return newOwnerId
+                        ? PermissionsActionHelper.changeOwner(dispatch, {
+                              itemId,
+                              newOwnerId,
+                              allUsers
+                          })
+                        : Promise.resolve();
+                })
+                .then(() =>
+                    PermissionsActionHelper.closePermissionManager(dispatch)
+                );
+        }
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(PermissionsManager);
index b7d5d57..ab6add8 100644 (file)
@@ -21,97 +21,154 @@ 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 {permissionTypes, changeOwnerMessage} from './PermissionsConstants.js';
+import { permissionTypes, changeOwnerMessage } from './PermissionsConstants.js';
 
 export const askForRightsMsg = () => {
-       return (
-               <div>
-                       <p>{i18n('Send a Contributor rights reguest to Owner')}</p>
-               </div>
-       );
+    return (
+        <div>
+            <p>{i18n('Send a Contributor rights reguest to Owner')}</p>
+        </div>
+    );
 };
 
-
 class Permissions extends React.Component {
-       constructor(props) {
-               super(props);
-               this.state = {
-                       itemUsers: props.itemUsers,
-                       newOwnerId: '',
-                       showChangeOwner: false
-               };
-       }
+    constructor(props) {
+        super(props);
+        this.state = {
+            itemUsers: props.itemUsers,
+            newOwnerId: '',
+            showChangeOwner: false
+        };
+    }
 
-       buildUserOptions() {
-               let {users, owner} = this.props;
-               return users.filter(user => user.userId !== owner.userId).map(item => {return {label: item.fullName, value: item.userId};});
-       }
+    buildUserOptions() {
+        let { users, owner } = this.props;
+        return users.filter(user => user.userId !== owner.userId).map(item => {
+            return { label: item.fullName, value: item.userId };
+        });
+    }
 
-       render() {
-               let {onCancel, owner} = this.props;
-               let {newOwnerId} = this.state;
-               return (
-                       <div className='manage-permissions-page'>
-                               <Form
-                                       hasButtons={true}
-                                       onSubmit={() => this.onsaveItemUsers()}
-                                       onReset={() => onCancel() }
-                                       labledButtons={true}>
-                                       <div className='manage-permissions-title'>{i18n('Owner')}</div>
-                                       <div className='owner-details'>
-                                               <span>{owner.fullName}</span>
-                                               <span className='change-owner' onClick={() => this.setState({showChangeOwner: !this.state.showChangeOwner})}>{i18n('Change Owner')}</span>
-                                       </div>
-                                       {this.state.showChangeOwner && <div className='change-owner-wrapper'>
-                                               <div className='change-owner-title'>
-                                                       <span className='manage-permissions-title' data-test-id='change-owner'>{i18n('Change Owner')}</span>
-                                                       <OverlayTrigger placement='right' trigger='click' overlay={
-                                                               <Tooltip id='manage-permissions-owner-tooltip' className='manage-permissions-owner-tooltip'>{i18n(changeOwnerMessage)}</Tooltip> }>
-                                                               <SVGIcon name='questionMark' />
-                                                       </OverlayTrigger>
-                                               </div>
-                                               <Select
-                                                       data-test-id='selected-owner'
-                                                       value={newOwnerId}
-                                                       onChange={(item) => this.setState({newOwnerId: item ? item.value : ''})}
-                                                       options={this.buildUserOptions()} />
-                                       </div>}
-                                       <div className='manage-permissions-title'>{i18n('Contributors')}</div>
-                                       <Select
-                                               data-test-id='selected-contributors'
-                                               value={this.state.itemUsers.map(item => item.userId)}
-                                               className='options-input contributors-select'
-                                               clearable={false}
-                                               onMultiSelectChanged={(value) => {this.onChangeItemUsers({itemUsers: value});}}
-                                               options={this.buildUserOptions()}
-                                               multi/>
-                               </Form>
-                       </div>
-               );
-       }
+    render() {
+        let { onCancel, owner } = this.props;
+        let { newOwnerId } = this.state;
+        return (
+            <div className="manage-permissions-page">
+                <Form
+                    hasButtons={true}
+                    onSubmit={() => this.onsaveItemUsers()}
+                    onReset={() => onCancel()}
+                    labledButtons={true}>
+                    <div className="manage-permissions-title">
+                        {i18n('Owner')}
+                    </div>
+                    <div className="owner-details">
+                        <span>{owner.fullName}</span>
+                        <span
+                            className="change-owner"
+                            onClick={() =>
+                                this.setState({
+                                    showChangeOwner: !this.state.showChangeOwner
+                                })
+                            }>
+                            {i18n('Change Owner')}
+                        </span>
+                    </div>
+                    {this.state.showChangeOwner && (
+                        <div className="change-owner-wrapper">
+                            <div className="change-owner-title">
+                                <span
+                                    className="manage-permissions-title"
+                                    data-test-id="change-owner">
+                                    {i18n('Change Owner')}
+                                </span>
+                                <OverlayTrigger
+                                    placement="right"
+                                    trigger="click"
+                                    overlay={
+                                        <Tooltip
+                                            id="manage-permissions-owner-tooltip"
+                                            className="manage-permissions-owner-tooltip">
+                                            {i18n(changeOwnerMessage)}
+                                        </Tooltip>
+                                    }>
+                                    <SVGIcon name="questionMark" />
+                                </OverlayTrigger>
+                            </div>
+                            <Select
+                                data-test-id="selected-owner"
+                                value={newOwnerId}
+                                onChange={item =>
+                                    this.setState({
+                                        newOwnerId: item ? item.value : ''
+                                    })
+                                }
+                                options={this.buildUserOptions()}
+                            />
+                        </div>
+                    )}
+                    <div className="manage-permissions-title">
+                        {i18n('Contributors')}
+                    </div>
+                    <Select
+                        data-test-id="selected-contributors"
+                        value={this.state.itemUsers.map(item => item.userId)}
+                        className="options-input contributors-select"
+                        clearable={false}
+                        onMultiSelectChanged={value => {
+                            this.onChangeItemUsers({ itemUsers: value });
+                        }}
+                        options={this.buildUserOptions()}
+                        multi
+                    />
+                </Form>
+            </div>
+        );
+    }
 
-       onChangeItemUsers({itemUsers}) {
-               this.setState({
-                       itemUsers: itemUsers.map(contributor => {
-                               let contributorFromProps = this.props.itemUsers.find(user => user.userId === contributor.userId);
-                               return {
-                                       userId: contributor.value,
-                                       fullName: contributor.label,
-                                       permission: contributorFromProps ? contributorFromProps.permission : permissionTypes.CONTRIBUTOR
-                               };
-                       })
-               });
-       }
+    onChangeItemUsers({ itemUsers }) {
+        this.setState({
+            itemUsers: itemUsers.map(contributor => {
+                let contributorFromProps = this.props.itemUsers.find(
+                    user => user.userId === contributor.userId
+                );
+                return {
+                    userId: contributor.value,
+                    fullName: contributor.label,
+                    permission: contributorFromProps
+                        ? contributorFromProps.permission
+                        : permissionTypes.CONTRIBUTOR
+                };
+            })
+        });
+    }
 
-       onsaveItemUsers() {
-               let {itemUsers: newUsers, newOwnerId} = this.state;
-               let {itemUsers: oldUsers, onSubmit, itemId, users} = this.props;
-               let addedUsersIds = newUsers.filter(newUser => !oldUsers.map(oldUser => oldUser.userId).includes(newUser.userId))
-                       .map(user => user.userId);
-               let removedUsersIds = oldUsers.filter(oldUser => !newUsers.map(newUser => newUser.userId).includes(oldUser.userId))
-                       .map(user => user.userId);
-               onSubmit({itemId, addedUsersIds, removedUsersIds, allUsers: users, newOwnerId});
-       }
+    onsaveItemUsers() {
+        let { itemUsers: newUsers, newOwnerId } = this.state;
+        let { itemUsers: oldUsers, onSubmit, itemId, users } = this.props;
+        let addedUsersIds = newUsers
+            .filter(
+                newUser =>
+                    !oldUsers
+                        .map(oldUser => oldUser.userId)
+                        .includes(newUser.userId)
+            )
+            .map(user => user.userId);
+        let removedUsersIds = oldUsers
+            .filter(
+                oldUser =>
+                    !newUsers
+                        .map(newUser => newUser.userId)
+                        .includes(oldUser.userId)
+            )
+            .map(user => user.userId);
+        onSubmit({
+            itemId,
+            addedUsersIds,
+            removedUsersIds,
+            allUsers: users,
+            newOwnerId
+        });
+    }
 }
 
 export default Permissions;
index b4ab789..6e817ae 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './PermissionsConstants.js';
+import { actionTypes } from './PermissionsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.ITEM_USERS_LOADED:
-                       return {
-                               owner: action.owner,
-                               contributors: action.contributors
-                       };
-               default:
-                       return state;
-       }
-};
\ No newline at end of file
+    switch (action.type) {
+        case actionTypes.ITEM_USERS_LOADED:
+            return {
+                owner: action.owner,
+                contributors: action.contributors
+            };
+        default:
+            return state;
+    }
+};
index 73ee5de..738e745 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import RevisionsView from './RevisionsView.jsx';
 import RevisionsActionHelper from './RevisionsActionHelper.js';
 
-export const mapStateToProps = ({revisions, users}) => {
-       return {
-               revisions: revisions,
-               users: users.usersList
-       };
+export const mapStateToProps = ({ revisions, users }) => {
+    return {
+        revisions: revisions,
+        users: users.usersList
+    };
 };
 
-export const mapActionsToProps = (dispatch, {itemId, version, itemType}) => {
-       return {
-               onCancel: () => RevisionsActionHelper.closeRevisionsView(dispatch),
-               onRevert: (revisionId) => {
-                       RevisionsActionHelper.revertToRevision(dispatch, {itemId, version, revisionId, itemType});
-               }
-       };
+export const mapActionsToProps = (dispatch, { itemId, version, itemType }) => {
+    return {
+        onCancel: () => RevisionsActionHelper.closeRevisionsView(dispatch),
+        onRevert: revisionId => {
+            RevisionsActionHelper.revertToRevision(dispatch, {
+                itemId,
+                version,
+                revisionId,
+                itemType
+            });
+        }
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(RevisionsView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(RevisionsView);
index 4fd9082..61ccad0 100644 (file)
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {actionsEnum as vcActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionsEnum as vcActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
 
 import Configuration from 'sdc-app/config/Configuration.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 
-import {actionTypes} from './RevisionsConstants.js';
+import { actionTypes } from './RevisionsConstants.js';
 
 function baseUrl(itemId, version) {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/items/${itemId}/versions/${version.id}`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/items/${itemId}/versions/${version.id}`;
 }
 
-function fetchRevisions(itemId, version){
-       let fetchUrl = `${baseUrl(itemId, version)}/revisions`;
-       return RestAPIUtil.fetch(fetchUrl);
+function fetchRevisions(itemId, version) {
+    let fetchUrl = `${baseUrl(itemId, version)}/revisions`;
+    return RestAPIUtil.fetch(fetchUrl);
 }
 
 function revertToRevision(itemId, version, revisionId) {
-       let putUrl = `${baseUrl(itemId, version)}/actions`;
-       let requestBody = {
-               action: vcActionsEnum.REVERT,
-               revisionRequest: {
-                       revisionId: revisionId
-               }
-       };
-       return RestAPIUtil.put(putUrl, requestBody);
+    let putUrl = `${baseUrl(itemId, version)}/actions`;
+    let requestBody = {
+        action: vcActionsEnum.REVERT,
+        revisionRequest: {
+            revisionId: revisionId
+        }
+    };
+    return RestAPIUtil.put(putUrl, requestBody);
 }
 
 const RevisionaActionHelper = {
-       openRevisionsView(dispatch, {itemId, version, itemType}) {
-               this.fetchRevisions(dispatch, {itemId, version}).then(() => {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                               data: {
-                                       modalComponentName: modalContentMapper.REVISIONS_LIST,
-                                       modalClassName: 'manage-revisions-modal',
-                                       title: i18n('Revert'),
-                                       modalComponentProps: {
-                                               itemId: itemId,
-                                               version: version,
-                                               itemType
-                                       }
-                               }
-                       });
-               });
-       },
+    openRevisionsView(dispatch, { itemId, version, itemType }) {
+        this.fetchRevisions(dispatch, { itemId, version }).then(() => {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.REVISIONS_LIST,
+                    modalClassName: 'manage-revisions-modal',
+                    title: i18n('Revert'),
+                    modalComponentProps: {
+                        itemId: itemId,
+                        version: version,
+                        itemType
+                    }
+                }
+            });
+        });
+    },
 
-       closeRevisionsView(dispatch) {
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-       },
+    closeRevisionsView(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+    },
 
+    fetchRevisions(dispatch, { itemId, version }) {
+        return fetchRevisions(itemId, version).then(response => {
+            dispatch({
+                type: actionTypes.ITEM_REVISIONS_LOADED,
+                response: response
+            });
+        });
+    },
 
-       fetchRevisions(dispatch, {itemId, version}) {
-               return fetchRevisions(itemId, version).then((response) => {
-                       dispatch({
-                               type: actionTypes.ITEM_REVISIONS_LOADED,
-                               response: response
-                       });
-               });
-       },
-
-       revertToRevision(dispatch, {itemId, version,  revisionId, itemType}) {
-               return revertToRevision(itemId, version, revisionId).then(() => {
-                       this.closeRevisionsView(dispatch);
-                       if (itemType === screenTypes.LICENSE_MODEL) {
-                               ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.LICENSE_MODEL_OVERVIEW, screenType: screenTypes.LICENSE_MODEL,
-                                       props: {licenseModelId: itemId, version}});
-                       } else {
-                               ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                       props: {softwareProductId: itemId, version}});
-                       }
-               });
-
-       }
+    revertToRevision(dispatch, { itemId, version, revisionId, itemType }) {
+        return revertToRevision(itemId, version, revisionId).then(() => {
+            this.closeRevisionsView(dispatch);
+            if (itemType === screenTypes.LICENSE_MODEL) {
+                ScreensHelper.loadScreen(dispatch, {
+                    screen: enums.SCREEN.LICENSE_MODEL_OVERVIEW,
+                    screenType: screenTypes.LICENSE_MODEL,
+                    props: { licenseModelId: itemId, version }
+                });
+            } else {
+                ScreensHelper.loadScreen(dispatch, {
+                    screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                    screenType: screenTypes.SOFTWARE_PRODUCT,
+                    props: { softwareProductId: itemId, version }
+                });
+            }
+        });
+    }
 };
 
 export default RevisionaActionHelper;
index 28a9fa0..dc1845c 100644 (file)
@@ -16,5 +16,5 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       ITEM_REVISIONS_LOADED: null
+    ITEM_REVISIONS_LOADED: null
 });
index 778350b..a3e6ce8 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './RevisionsConstants.js';
+import { actionTypes } from './RevisionsConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.ITEM_REVISIONS_LOADED:
-                       return  action.response.results;
-               default:
-                       return state;
-       }
-};
\ No newline at end of file
+    switch (action.type) {
+        case actionTypes.ITEM_REVISIONS_LOADED:
+            return action.response.results;
+        default:
+            return state;
+    }
+};
index d6ef604..1fc8c06 100644 (file)
@@ -23,65 +23,111 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
 
-
 class RevisionsView extends React.Component {
-       constructor(props) {
-               super(props);
-               this.state = {
-                       revertId : null
-               };
-       }
-
-       render() {
-               let {onCancel, onRevert, revisions, users} = this.props;
-               return (
-                       <div className='manage-revisions-page'>
-                               <Form
-                                       hasButtons={true}
-                                       onSubmit={() => onRevert(this.state.revertId)}
-                                       onReset={() => onCancel() }
-                                       submitButtonText={i18n('Revert')}
-                                       labledButtons={true}>
-                                       <ListEditorView
-                                               title={i18n('Select a Commit')}
-                                               isReadOnlyMode={false}>
-                                               {revisions.map((revision) => {
-                                                       return (
-                                                               <div key={revision.id} data-test-id='revision-list-item' className={`revision-list-item ${this.state.revertId === revision.id ? 'selected' : ''}`}>
-                                                                       <ListEditorItemView
-                                                                               isReadOnlyMode={false}
-                                                                               onSelect={() => this.setState({revertId : revision.id})}>
-                                                                                       <ListEditorItemViewField>
-                                                                                               <div className='revision-list-item-fields'>
-                                                                                                   <div data-test-id='revision-user' className='revision-user'>
-                                                                                                           <SVGIcon name='user' label={users.find(userObject => userObject.userId === revision.user).fullName} labelPosition='right'/>
-                                                                                                   </div>
-                                                                                                       <div className='revision-date' data-test-id='revision-date'>
-                                                                                                               <span className='revision-date'>{i18n.dateNormal(revision.time, {
-                                                                                                                       year: 'numeric', month: 'numeric', day: 'numeric'
-                                                                                                               })}</span>
-                                                                                                               <span className='revision-time'>{i18n.dateNormal(revision.time, {
-                                                                                                                       hour: 'numeric', minute: 'numeric',
-                                                                                                                       hour12: true
-                                                                                                               })}</span>
-                                                                                                       </div>
-                                                                                                       <div className='revision-message'data-test-id='revision-message'>
-                                                                                                               {revision.message && <ShowMore anchorClass='more-less' lines={2} more={i18n('More')} less={i18n('Less')}>
-                                                                                                               {revision.message}
-                                                                                                       </ShowMore>}</div>
-                                                                                               </div>
-                                                                                       </ListEditorItemViewField>
-                                                                       </ListEditorItemView>
-                                                               </div>
-
-                                                       );
-                                               })}
-                                       </ListEditorView>
-                               </Form>
-                       </div>
-               );
-       }
+    constructor(props) {
+        super(props);
+        this.state = {
+            revertId: null
+        };
+    }
 
+    render() {
+        let { onCancel, onRevert, revisions, users } = this.props;
+        return (
+            <div className="manage-revisions-page">
+                <Form
+                    hasButtons={true}
+                    onSubmit={() => onRevert(this.state.revertId)}
+                    onReset={() => onCancel()}
+                    submitButtonText={i18n('Revert')}
+                    labledButtons={true}>
+                    <ListEditorView
+                        title={i18n('Select a Commit')}
+                        isReadOnlyMode={false}>
+                        {revisions.map(revision => {
+                            return (
+                                <div
+                                    key={revision.id}
+                                    data-test-id="revision-list-item"
+                                    className={`revision-list-item ${
+                                        this.state.revertId === revision.id
+                                            ? 'selected'
+                                            : ''
+                                    }`}>
+                                    <ListEditorItemView
+                                        isReadOnlyMode={false}
+                                        onSelect={() =>
+                                            this.setState({
+                                                revertId: revision.id
+                                            })
+                                        }>
+                                        <ListEditorItemViewField>
+                                            <div className="revision-list-item-fields">
+                                                <div
+                                                    data-test-id="revision-user"
+                                                    className="revision-user">
+                                                    <SVGIcon
+                                                        name="user"
+                                                        label={
+                                                            users.find(
+                                                                userObject =>
+                                                                    userObject.userId ===
+                                                                    revision.user
+                                                            ).fullName
+                                                        }
+                                                        labelPosition="right"
+                                                    />
+                                                </div>
+                                                <div
+                                                    className="revision-date"
+                                                    data-test-id="revision-date">
+                                                    <span className="revision-date">
+                                                        {i18n.dateNormal(
+                                                            revision.time,
+                                                            {
+                                                                year: 'numeric',
+                                                                month:
+                                                                    'numeric',
+                                                                day: 'numeric'
+                                                            }
+                                                        )}
+                                                    </span>
+                                                    <span className="revision-time">
+                                                        {i18n.dateNormal(
+                                                            revision.time,
+                                                            {
+                                                                hour: 'numeric',
+                                                                minute:
+                                                                    'numeric',
+                                                                hour12: true
+                                                            }
+                                                        )}
+                                                    </span>
+                                                </div>
+                                                <div
+                                                    className="revision-message"
+                                                    data-test-id="revision-message">
+                                                    {revision.message && (
+                                                        <ShowMore
+                                                            anchorClass="more-less"
+                                                            lines={2}
+                                                            more={i18n('More')}
+                                                            less={i18n('Less')}>
+                                                            {revision.message}
+                                                        </ShowMore>
+                                                    )}
+                                                </div>
+                                            </div>
+                                        </ListEditorItemViewField>
+                                    </ListEditorItemView>
+                                </div>
+                            );
+                        })}
+                    </ListEditorView>
+                </Form>
+            </div>
+        );
+    }
 }
 
 export default RevisionsView;
index b484f5e..9faa6ff 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductConstants.js';
+import { actionTypes } from './SoftwareProductConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED:
-                       return [...action.response.results];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED:
+            return [...action.response.results];
+        default:
+            return state;
+    }
 };
index 396f65f..f91c8f3 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductConstants.js';
+import { actionTypes } from './SoftwareProductConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED:
-                       return [...action.response.results];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED:
+            return [...action.response.results];
+        default:
+            return state;
+    }
 };
index e3ea7e1..db3cc04 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
 
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
-import {onboardingMethod as onboardingMethodTypes, onboardingOriginTypes} from './SoftwareProductConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
+import {
+    onboardingMethod as onboardingMethodTypes,
+    onboardingOriginTypes
+} from './SoftwareProductConstants.js';
 import SoftwareProductActionHelper from './SoftwareProductActionHelper.js';
 import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
 import PermissionsActionHelper from './../permissions/PermissionsActionHelper.js';
 import RevisionsActionHelper from './../revisions/RevisionsActionHelper.js';
 import HeatSetupActionHelper from './attachments/setup/HeatSetupActionHelper.js';
 import { actionsEnum as versionControllerActions } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
-import {onboardingMethod as onboardingMethodType} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-import {SyncStates} from 'sdc-app/common/merge/MergeEditorConstants.js';
-import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
+import { onboardingMethod as onboardingMethodType } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { SyncStates } from 'sdc-app/common/merge/MergeEditorConstants.js';
+import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
 
 function getActiveNavigationId(screen, componentId) {
-       let activeItemId = componentId ? screen + '|' + componentId : screen;
-       return activeItemId;
+    let activeItemId = componentId ? screen + '|' + componentId : screen;
+    return activeItemId;
 }
 
-const buildComponentNavigationBarGroups = ({componentId, meta}) => {
-       const groups = ([
-               {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL + '|' + componentId,
-                       name: i18n('General'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE + '|' + componentId,
-                       name: i18n('Compute'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING + '|' + componentId,
-                       name: i18n('High Availability & Load Balancing'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK + '|' + componentId,
-                       name: i18n('Networks'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE + '|' + componentId,
-                       name: i18n('Storage'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES + '|' + componentId,
-                       name: i18n('Images'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES + '|' + componentId,
-                       name: i18n('Process Details'),
-                       disabled: false,
-                       meta
-               }, {
-                       id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING + '|' + componentId,
-                       name: i18n('Monitoring'),
-                       disabled: false,
-                       meta
-               }
-       ]);
+const buildComponentNavigationBarGroups = ({ componentId, meta }) => {
+    const groups = [
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL +
+                '|' +
+                componentId,
+            name: i18n('General'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE +
+                '|' +
+                componentId,
+            name: i18n('Compute'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING +
+                '|' +
+                componentId,
+            name: i18n('High Availability & Load Balancing'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK +
+                '|' +
+                componentId,
+            name: i18n('Networks'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE +
+                '|' +
+                componentId,
+            name: i18n('Storage'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES +
+                '|' +
+                componentId,
+            name: i18n('Images'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES +
+                '|' +
+                componentId,
+            name: i18n('Process Details'),
+            disabled: false,
+            meta
+        },
+        {
+            id:
+                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING +
+                '|' +
+                componentId,
+            name: i18n('Monitoring'),
+            disabled: false,
+            meta
+        }
+    ];
 
-       return groups;
+    return groups;
 };
 
-const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}) => {
-       const {softwareProductEditor: {data: currentSoftwareProduct = {}}} = softwareProduct;
-       const {id, name, onboardingMethod, candidateOnboardingOrigin, onboardingOrigin} = currentSoftwareProduct;
-       const groups = [{
-               id: id,
-               name: name,
-               items: [
-                       {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
-                               name: i18n('Overview'),
-                               disabled: false,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS,
-                               name: i18n('General'),
-                               disabled: false,
-                               meta
-                       },
-                       {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT,
-                               name: i18n('Deployment Flavors'),
-                               disabled: false,
-                               hidden: onboardingMethod !== onboardingMethodTypes.MANUAL,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES,
-                               name: i18n('Process Details'),
-                               disabled: false,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS,
-                               name: i18n('Networks'),
-                               disabled: false,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS,
-                               name: i18n('Attachments'),
-                               disabled: false,
-                               hidden: !candidateOnboardingOrigin && !onboardingOrigin,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG,
-                               name: i18n('Activity Log'),
-                               disabled: false,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES,
-                               name: i18n('Component Dependencies'),
-                               hidden: componentsList.length <= 1,
-                               disabled: false,
-                               meta
-                       }, {
-                               id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS,
-                               name: i18n('Components'),
-                               hidden: componentsList.length <= 0,
-                               meta,
-                               expanded: mapOfExpandedIds[enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS] === true && screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
-                               items: [
-                                       ...componentsList.map(({id, displayName}) => ({
-                                               id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + '|' + id,
-                                               name: displayName,
-                                               meta,
-                                               expanded: mapOfExpandedIds[enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + '|' + id] === true  && screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
-                                               items: buildComponentNavigationBarGroups({componentId: id, meta})
-                                       }))
-                               ]
-                       }
-               ]
-       }];
-       let activeItemId = getActiveNavigationId(screen, componentId);
-       return {
-               activeItemId, groups, disabled: !!candidateOnboardingOrigin
-       };
+const buildNavigationBarProps = ({
+    softwareProduct,
+    meta,
+    screen,
+    componentId,
+    componentsList,
+    mapOfExpandedIds
+}) => {
+    const {
+        softwareProductEditor: { data: currentSoftwareProduct = {} }
+    } = softwareProduct;
+    const {
+        id,
+        name,
+        onboardingMethod,
+        candidateOnboardingOrigin,
+        onboardingOrigin
+    } = currentSoftwareProduct;
+    const groups = [
+        {
+            id: id,
+            name: name,
+            items: [
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                    name: i18n('Overview'),
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS,
+                    name: i18n('General'),
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT,
+                    name: i18n('Deployment Flavors'),
+                    disabled: false,
+                    hidden: onboardingMethod !== onboardingMethodTypes.MANUAL,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES,
+                    name: i18n('Process Details'),
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS,
+                    name: i18n('Networks'),
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS,
+                    name: i18n('Attachments'),
+                    disabled: false,
+                    hidden: !candidateOnboardingOrigin && !onboardingOrigin,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG,
+                    name: i18n('Activity Log'),
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES,
+                    name: i18n('Component Dependencies'),
+                    hidden: componentsList.length <= 1,
+                    disabled: false,
+                    meta
+                },
+                {
+                    id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS,
+                    name: i18n('Components'),
+                    hidden: componentsList.length <= 0,
+                    meta,
+                    expanded:
+                        mapOfExpandedIds[
+                            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS
+                        ] === true &&
+                        screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                    items: [
+                        ...componentsList.map(({ id, displayName }) => ({
+                            id:
+                                enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS +
+                                '|' +
+                                id,
+                            name: displayName,
+                            meta,
+                            expanded:
+                                mapOfExpandedIds[
+                                    enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS +
+                                        '|' +
+                                        id
+                                ] === true &&
+                                screen !==
+                                    enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                            items: buildComponentNavigationBarGroups({
+                                componentId: id,
+                                meta
+                            })
+                        }))
+                    ]
+                }
+            ]
+        }
+    ];
+    let activeItemId = getActiveNavigationId(screen, componentId);
+    return {
+        activeItemId,
+        groups,
+        disabled: !!candidateOnboardingOrigin
+    };
 };
 
-const buildVersionControllerProps = ({softwareProduct, versions, currentVersion, permissions, userInfo, isArchived, usersList, itemPermission, isReadOnlyMode}) => {
-       const {softwareProductEditor = {data: {}}} = softwareProduct;
-       const {isValidityData = true, data: {name, onboardingMethod, candidateOnboardingOrigin}} = softwareProductEditor;
-       
-       return {
-               version: currentVersion,
-               viewableVersions: versions,
-               isFormDataValid: isValidityData,
-               permissions,
-               itemName: name,
-               itemPermission,
-               isReadOnlyMode,
-               isArchived,
-               userInfo,
-               usersList,
-               isManual: onboardingMethod === onboardingMethodType.MANUAL,
-               candidateInProcess: !!candidateOnboardingOrigin
-       };
+const buildVersionControllerProps = ({
+    softwareProduct,
+    versions,
+    currentVersion,
+    permissions,
+    userInfo,
+    isArchived,
+    usersList,
+    itemPermission,
+    isReadOnlyMode
+}) => {
+    const { softwareProductEditor = { data: {} } } = softwareProduct;
+    const {
+        isValidityData = true,
+        data: { name, onboardingMethod, candidateOnboardingOrigin }
+    } = softwareProductEditor;
+
+    return {
+        version: currentVersion,
+        viewableVersions: versions,
+        isFormDataValid: isValidityData,
+        permissions,
+        itemName: name,
+        itemPermission,
+        isReadOnlyMode,
+        isArchived,
+        userInfo,
+        usersList,
+        isManual: onboardingMethod === onboardingMethodType.MANUAL,
+        candidateInProcess: !!candidateOnboardingOrigin
+    };
 };
 
-function buildMeta({softwareProduct, componentId, softwareProductDependencies, isReadOnlyMode}) {
-       const {softwareProductEditor, softwareProductComponents, softwareProductQuestionnaire, softwareProductAttachments} = softwareProduct;
-       const {data: currentSoftwareProduct = {}} = softwareProductEditor;
-       const {version, onboardingOrigin, candidateOnboardingOrigin} = currentSoftwareProduct;
-       const {qdata} = softwareProductQuestionnaire;
-       const {heatSetup, heatSetupCache} = softwareProductAttachments;
-       let currentComponentMeta = {};
-       if(componentId) {
-               const {componentEditor: {data: componentData = {} , qdata: componentQdata}} = softwareProductComponents;
-               currentComponentMeta = {componentData, componentQdata};
-       }
-       const meta = {softwareProduct: currentSoftwareProduct, qdata, version, onboardingOrigin, candidateOnboardingOrigin, heatSetup, heatSetupCache,
-               isReadOnlyMode, currentComponentMeta, softwareProductDependencies};
-       return meta;
+function buildMeta({
+    softwareProduct,
+    componentId,
+    softwareProductDependencies,
+    isReadOnlyMode
+}) {
+    const {
+        softwareProductEditor,
+        softwareProductComponents,
+        softwareProductQuestionnaire,
+        softwareProductAttachments
+    } = softwareProduct;
+    const { data: currentSoftwareProduct = {} } = softwareProductEditor;
+    const {
+        version,
+        onboardingOrigin,
+        candidateOnboardingOrigin
+    } = currentSoftwareProduct;
+    const { qdata } = softwareProductQuestionnaire;
+    const { heatSetup, heatSetupCache } = softwareProductAttachments;
+    let currentComponentMeta = {};
+    if (componentId) {
+        const {
+            componentEditor: { data: componentData = {}, qdata: componentQdata }
+        } = softwareProductComponents;
+        currentComponentMeta = { componentData, componentQdata };
+    }
+    const meta = {
+        softwareProduct: currentSoftwareProduct,
+        qdata,
+        version,
+        onboardingOrigin,
+        candidateOnboardingOrigin,
+        heatSetup,
+        heatSetupCache,
+        isReadOnlyMode,
+        currentComponentMeta,
+        softwareProductDependencies
+    };
+    return meta;
 }
 
 const mapStateToProps = (
-       {
-               softwareProduct,
-               users: {usersList, userInfo},
-               versionsPage: {versionsList: {versions}, permissions}
-       },
-       {
-               currentScreen: {screen, itemPermission, props: {version: currentVersion, componentId, isReadOnlyMode}}
-       }
+    {
+        softwareProduct,
+        users: { usersList, userInfo },
+        versionsPage: { versionsList: { versions }, permissions }
+    },
+    {
+        currentScreen: {
+            screen,
+            itemPermission,
+            props: { version: currentVersion, componentId, isReadOnlyMode }
+        }
+    }
 ) => {
-       const {softwareProductEditor, softwareProductComponents, softwareProductDependencies} = softwareProduct;
-       const {mapOfExpandedIds = []} = softwareProductEditor;
-       const {componentsList = []} = softwareProductComponents;
+    const {
+        softwareProductEditor,
+        softwareProductComponents,
+        softwareProductDependencies
+    } = softwareProduct;
+    const { mapOfExpandedIds = [] } = softwareProductEditor;
+    const { componentsList = [] } = softwareProductComponents;
 
-       const meta = buildMeta({softwareProduct, componentId, softwareProductDependencies, isReadOnlyMode});
-       return {
-               versionControllerProps: buildVersionControllerProps({
-                       softwareProduct,
-                       versions,
-                       currentVersion,
-                       userInfo,
-                       usersList,
-                       isArchived: itemPermission.isArchived,
-                       permissions,
-                       itemPermission: {...itemPermission, isDirty: true},
-                       isReadOnlyMode
-               }),
-               navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}),
-               meta
-       };
+    const meta = buildMeta({
+        softwareProduct,
+        componentId,
+        softwareProductDependencies,
+        isReadOnlyMode
+    });
+    return {
+        versionControllerProps: buildVersionControllerProps({
+            softwareProduct,
+            versions,
+            currentVersion,
+            userInfo,
+            usersList,
+            isArchived: itemPermission.isArchived,
+            permissions,
+            itemPermission: { ...itemPermission, isDirty: true },
+            isReadOnlyMode
+        }),
+        navigationBarProps: buildNavigationBarProps({
+            softwareProduct,
+            meta,
+            screen,
+            componentId,
+            componentsList,
+            mapOfExpandedIds
+        }),
+        meta
+    };
 };
 
-const autoSaveBeforeNavigate = ({dispatch, screen, softwareProductId, version, componentId,
-               meta: {isReadOnlyMode, softwareProduct, qdata,
-               currentComponentMeta: {componentData, componentQdata}}}) => {
-       let promise;
-       if (isReadOnlyMode) {
-               promise = Promise.resolve();
-       } else {
-               switch(screen) {
-                       case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
-                               promise = SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, version, qdata});
-                               break;
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
-                               promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch,
-                                       {softwareProductId, version, vspComponentId: componentId, componentData, qdata: componentQdata});
-                               break;
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
-                       case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
-                               promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata: componentQdata});
-                               break;
-                       default:
-                               promise = Promise.resolve();
-                               break;
-               }
-       }
-       return promise;
+const autoSaveBeforeNavigate = ({
+    dispatch,
+    screen,
+    softwareProductId,
+    version,
+    componentId,
+    meta: {
+        isReadOnlyMode,
+        softwareProduct,
+        qdata,
+        currentComponentMeta: { componentData, componentQdata }
+    }
+}) => {
+    let promise;
+    if (isReadOnlyMode) {
+        promise = Promise.resolve();
+    } else {
+        switch (screen) {
+            case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
+                promise = SoftwareProductActionHelper.updateSoftwareProduct(
+                    dispatch,
+                    { softwareProduct, version, qdata }
+                );
+                break;
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+                promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        version,
+                        vspComponentId: componentId,
+                        componentData,
+                        qdata: componentQdata
+                    }
+                );
+                break;
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
+            case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+                promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        version,
+                        vspComponentId: componentId,
+                        qdata: componentQdata
+                    }
+                );
+                break;
+            default:
+                promise = Promise.resolve();
+                break;
+        }
+    }
+    return promise;
 };
 
+const mapActionsToProps = (
+    dispatch,
+    {
+        currentScreen: {
+            screen,
+            props: {
+                softwareProductId,
+                licenseModelId,
+                version,
+                componentId: currentComponentId
+            }
+        }
+    }
+) => {
+    const props = {
+        onVersionSwitching: (versionToSwitch, meta) => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: {
+                    softwareProductId: meta.softwareProduct.id,
+                    version: versionToSwitch
+                }
+            });
+        },
+        onOpenPermissions: ({ users }) => {
+            return PermissionsActionHelper.fetchItemUsers(dispatch, {
+                itemId: softwareProductId,
+                allUsers: users
+            });
+        },
+        onOpenRevisionsModal: () => {
+            return RevisionsActionHelper.openRevisionsView(dispatch, {
+                itemId: softwareProductId,
+                version: version,
+                itemType: screenTypes.SOFTWARE_PRODUCT
+            });
+        },
+        onOpenCommentCommitModal: ({ onCommit, title }) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.COMMIT_COMMENT,
+                    modalComponentProps: {
+                        onCommit,
+                        type: CommitModalType.COMMIT
+                    },
+                    title
+                }
+            }),
+        onMoreVersionsClick: ({ itemName, users }) => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: {
+                    softwareProductId,
+                    softwareProduct: {
+                        name: itemName,
+                        vendorId: licenseModelId
+                    },
+                    usersList: users
+                }
+            });
+        },
+        onToggle: (groups, itemIdToExpand) =>
+            groups.map(({ items }) =>
+                SoftwareProductActionHelper.toggleNavigationItems(dispatch, {
+                    items,
+                    itemIdToExpand
+                })
+            ),
+        onNavigate: ({ id, meta, newVersion }) => {
+            let navigationVersion = newVersion || version;
+            let {
+                onboardingOrigin,
+                candidateOnboardingOrigin,
+                heatSetup,
+                heatSetupCache
+            } = meta;
+            let heatSetupPopupPromise =
+                screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
+                    ? HeatSetupActionHelper.heatSetupLeaveConfirmation(
+                          dispatch,
+                          { softwareProductId, heatSetup, heatSetupCache }
+                      )
+                    : Promise.resolve();
+            let preNavigate = meta
+                ? autoSaveBeforeNavigate({
+                      dispatch,
+                      screen,
+                      meta,
+                      version,
+                      softwareProductId,
+                      componentId: currentComponentId
+                  })
+                : Promise.resolve();
+            version = version || (meta ? meta.version : undefined);
+            Promise.all([preNavigate, heatSetupPopupPromise])
+                .then(() => {
+                    let [nextScreen, nextComponentId] = id.split('|');
+                    if (
+                        nextScreen ===
+                            enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS &&
+                        nextComponentId &&
+                        nextComponentId === currentComponentId
+                    ) {
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: nextScreen,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                version: navigationVersion
+                            }
+                        });
+                    } else {
+                        if (
+                            nextScreen ===
+                            enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
+                        ) {
+                            if (
+                                onboardingOrigin ===
+                                    onboardingOriginTypes.ZIP ||
+                                candidateOnboardingOrigin ===
+                                    onboardingOriginTypes.ZIP
+                            ) {
+                                nextScreen =
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP;
+                            } else if (
+                                onboardingOrigin === onboardingOriginTypes.CSAR
+                            ) {
+                                nextScreen =
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION;
+                            }
+                        }
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen: nextScreen,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                version: navigationVersion,
+                                componentId: nextComponentId
+                            }
+                        });
+                    }
+                })
+                .catch(e => {
+                    console.error(e);
+                });
+        }
+    };
 
-const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {softwareProductId, licenseModelId, version, componentId: currentComponentId}}}) => {
-
-       const props = {
-               onVersionSwitching: (versionToSwitch, meta) => {
-                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                               props: {softwareProductId: meta.softwareProduct.id, version: versionToSwitch}});
-               },
-               onOpenPermissions: ({users}) => {
-                       return PermissionsActionHelper.fetchItemUsers(dispatch, {itemId: softwareProductId, allUsers: users});
-               },
-               onOpenRevisionsModal: () => {
-                       return RevisionsActionHelper.openRevisionsView(dispatch, {itemId: softwareProductId, version: version, itemType: screenTypes.SOFTWARE_PRODUCT});
-               },
-               onOpenCommentCommitModal: ({onCommit, title}) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.COMMIT_COMMENT,
-                               modalComponentProps: {
-                                       onCommit,
-                                       type: CommitModalType.COMMIT
-                               },
-                               title
-                       }
-               }),
-               onMoreVersionsClick: ({itemName, users}) => {
-                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                               props: {softwareProductId, softwareProduct: {name: itemName, vendorId: licenseModelId}, usersList: users}});
-
-               },
-               onToggle: (groups, itemIdToExpand) => groups.map(({items}) => SoftwareProductActionHelper.toggleNavigationItems(dispatch, {items, itemIdToExpand})),
-               onNavigate: ({id, meta, newVersion}) => {
-                       let navigationVersion = newVersion || version;
-                       let {onboardingOrigin, candidateOnboardingOrigin, heatSetup, heatSetupCache} = meta;
-                       let heatSetupPopupPromise = screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS ?
-                                                               HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) :
-                                                               Promise.resolve();
-                       let preNavigate = meta ? autoSaveBeforeNavigate({dispatch, screen, meta, version, softwareProductId, componentId: currentComponentId}) : Promise.resolve();
-                       version = version || (meta ? meta.version : undefined);
-                       Promise.all([preNavigate, heatSetupPopupPromise]).then(() => {
-                               let [nextScreen, nextComponentId] = id.split('|');
-                               if(nextScreen === enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS && nextComponentId && nextComponentId === currentComponentId) {
-                                       ScreensHelper.loadScreen(dispatch, {
-                                               screen: nextScreen, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, version: navigationVersion}
-                                       });
-                               }
-                               else {
-                                       if(nextScreen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS) {
-                                               if(onboardingOrigin === onboardingOriginTypes.ZIP || candidateOnboardingOrigin === onboardingOriginTypes.ZIP) {
-                                                       nextScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP;
-                                               }
-                                               else if(onboardingOrigin === onboardingOriginTypes.CSAR) {
-                                                       nextScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION;
-                                               }
-                                       }
-                                       ScreensHelper.loadScreen(dispatch, {
-                                               screen: nextScreen, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, version: navigationVersion, componentId: nextComponentId}
-                                       });
-                               }
-                       }).catch((e) => {console.error(e);});
-               }
-       };
-
-       switch (screen) {
-               case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
-               case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
-               case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
-               case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
-               case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
-               case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
-               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
-               case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
-               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
-               case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
-                       props.onSave = () => Promise.resolve();
-                       break;
-               default:
-                       props.onSave = ({softwareProduct, qdata}) => SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata, version});
-                       break;
-       }
-
+    switch (screen) {
+        case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
+        case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
+        case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
+        case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
+        case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+        case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
+        case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
+        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+        case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+            props.onSave = () => Promise.resolve();
+            break;
+        default:
+            props.onSave = ({ softwareProduct, qdata }) =>
+                SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
+                    softwareProduct,
+                    qdata,
+                    version
+                });
+            break;
+    }
 
-       props.onVersionControllerAction = (action, version, comment, meta) => {
-               let {heatSetup, heatSetupCache} = meta;
-               let autoSavePromise = meta ? autoSaveBeforeNavigate({dispatch, screen, meta, version, softwareProductId, componentId: currentComponentId}) : Promise.resolve();
-               let heatSetupPopupPromise = screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS && action === versionControllerActions.COMMIT ?
-                                                               HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) :
-                                                               Promise.resolve();
-               Promise.all([autoSavePromise, heatSetupPopupPromise]).then(() => {
-                       return SoftwareProductActionHelper.performVCAction(dispatch, {softwareProductId, action, version, comment, meta}).then(updatedVersion => {
-                               const inMerge = updatedVersion && updatedVersion.state && updatedVersion.state.synchronizationState === SyncStates.MERGE;
-                               if((action === versionControllerActions.SYNC && !inMerge) ||
-                                        ((action === versionControllerActions.COMMIT || action === versionControllerActions.SYNC) && updatedVersion.status === catalogItemStatuses.CERTIFIED)) {
-                                       ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: screen, props: {softwareProductId, version: updatedVersion}});
-                               } else {
-                                       ScreensHelper.loadScreen(dispatch, {screen, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, version: updatedVersion, componentId: currentComponentId}});
-                               }
-                       });
-               }).catch((e) => {console.error(e);});
-       };
+    props.onVersionControllerAction = (action, version, comment, meta) => {
+        let { heatSetup, heatSetupCache } = meta;
+        let autoSavePromise = meta
+            ? autoSaveBeforeNavigate({
+                  dispatch,
+                  screen,
+                  meta,
+                  version,
+                  softwareProductId,
+                  componentId: currentComponentId
+              })
+            : Promise.resolve();
+        let heatSetupPopupPromise =
+            screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS &&
+            action === versionControllerActions.COMMIT
+                ? HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {
+                      softwareProductId,
+                      heatSetup,
+                      heatSetupCache
+                  })
+                : Promise.resolve();
+        Promise.all([autoSavePromise, heatSetupPopupPromise])
+            .then(() => {
+                return SoftwareProductActionHelper.performVCAction(dispatch, {
+                    softwareProductId,
+                    action,
+                    version,
+                    comment,
+                    meta
+                }).then(updatedVersion => {
+                    const inMerge =
+                        updatedVersion &&
+                        updatedVersion.state &&
+                        updatedVersion.state.synchronizationState ===
+                            SyncStates.MERGE;
+                    if (
+                        (action === versionControllerActions.SYNC &&
+                            !inMerge) ||
+                        ((action === versionControllerActions.COMMIT ||
+                            action === versionControllerActions.SYNC) &&
+                            updatedVersion.status ===
+                                catalogItemStatuses.CERTIFIED)
+                    ) {
+                        ScreensHelper.loadLandingScreen(dispatch, {
+                            previousScreenName: screen,
+                            props: {
+                                softwareProductId,
+                                version: updatedVersion
+                            }
+                        });
+                    } else {
+                        ScreensHelper.loadScreen(dispatch, {
+                            screen,
+                            screenType: screenTypes.SOFTWARE_PRODUCT,
+                            props: {
+                                softwareProductId,
+                                version: updatedVersion,
+                                componentId: currentComponentId
+                            }
+                        });
+                    }
+                });
+            })
+            .catch(e => {
+                console.error(e);
+            });
+    };
 
-       props.onManagePermissions = () => PermissionsActionHelper.openPermissonsManager(dispatch, {itemId: softwareProductId, askForRights: false});
-       return props;
+    props.onManagePermissions = () =>
+        PermissionsActionHelper.openPermissonsManager(dispatch, {
+            itemId: softwareProductId,
+            askForRights: false
+        });
+    return props;
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(TabulatedEditor);
index 42786bf..4a2d7a2 100644 (file)
@@ -21,553 +21,769 @@ import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseMod
 import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
 
-import {actionTypes, onboardingOriginTypes, PRODUCT_QUESTIONNAIRE, forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {
+    actionTypes,
+    onboardingOriginTypes,
+    PRODUCT_QUESTIONNAIRE,
+    forms
+} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
 import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
-import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
-import {actionTypes as HeatSetupActions} from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
-import {actionTypes as featureGroupsActionConstants} from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js';
-import {actionTypes as licenseAgreementActionTypes} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
-import {actionTypes as componentActionTypes} from './components/SoftwareProductComponentsConstants.js';
+import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import { actionTypes as HeatSetupActions } from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
+import { actionTypes as featureGroupsActionConstants } from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js';
+import { actionTypes as licenseAgreementActionTypes } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
+import { actionTypes as componentActionTypes } from './components/SoftwareProductComponentsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {default as ItemsHelper} from 'sdc-app/common/helpers/ItemsHelper.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { default as ItemsHelper } from 'sdc-app/common/helpers/ItemsHelper.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
-import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
-import {actionTypes as commonActionTypes} from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
+import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
+import { actionTypes as commonActionTypes } from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import {itemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
-import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
 import getValue from 'nfvo-utils/getValue.js';
 
 function getLicensingData(licensingData = {}) {
-       const {licenseAgreement, featureGroups} = licensingData;
-       const newlicenseAgreement = getValue(licenseAgreement);
-       const newfeatureGroups = getValue(featureGroups);
-       return newlicenseAgreement ? {
-               licenseAgreement: newlicenseAgreement,
-               featureGroups: newfeatureGroups
-       } : undefined;
-};
+    const { licenseAgreement, featureGroups } = licensingData;
+    const newlicenseAgreement = getValue(licenseAgreement);
+    const newfeatureGroups = getValue(featureGroups);
+    return newlicenseAgreement
+        ? {
+              licenseAgreement: newlicenseAgreement,
+              featureGroups: newfeatureGroups
+          }
+        : undefined;
+}
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/`;
 }
 function softwareProductCategoriesUrl() {
-       const restCatalogPrefix = Configuration.get('restCatalogPrefix');
-       return `${restCatalogPrefix}/v1/categories/resources/`;
+    const restCatalogPrefix = Configuration.get('restCatalogPrefix');
+    return `${restCatalogPrefix}/v1/categories/resources/`;
 }
 
 function uploadFile(vspId, formData, version) {
-       return RestAPIUtil.post(`${baseUrl()}${vspId}/versions/${version.id}/orchestration-template-candidate`, formData);
-
+    return RestAPIUtil.post(
+        `${baseUrl()}${vspId}/versions/${
+            version.id
+        }/orchestration-template-candidate`,
+        formData
+    );
 }
 
-function putSoftwareProduct({softwareProduct, version}) {
-       return RestAPIUtil.put(`${baseUrl()}${softwareProduct.id}/versions/${version.id}`, {
-               name: softwareProduct.name,
-               description: softwareProduct.description,
-               category: softwareProduct.category,
-               subCategory: softwareProduct.subCategory,
-               vendorId: softwareProduct.vendorId,
-               vendorName: softwareProduct.vendorName,
-               licensingVersion: softwareProduct.licensingVersion ? softwareProduct.licensingVersion : undefined,
-               icon: softwareProduct.icon,
-               licensingData: getLicensingData(softwareProduct.licensingData)
-       });
+function putSoftwareProduct({ softwareProduct, version }) {
+    return RestAPIUtil.put(
+        `${baseUrl()}${softwareProduct.id}/versions/${version.id}`,
+        {
+            name: softwareProduct.name,
+            description: softwareProduct.description,
+            category: softwareProduct.category,
+            subCategory: softwareProduct.subCategory,
+            vendorId: softwareProduct.vendorId,
+            vendorName: softwareProduct.vendorName,
+            licensingVersion: softwareProduct.licensingVersion
+                ? softwareProduct.licensingVersion
+                : undefined,
+            icon: softwareProduct.icon,
+            licensingData: getLicensingData(softwareProduct.licensingData)
+        }
+    );
 }
 
 function putSoftwareProductQuestionnaire(vspId, qdata, version) {
-       return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`, qdata);
+    return RestAPIUtil.put(
+        `${baseUrl()}${vspId}/versions/${version.id}/questionnaire`,
+        qdata
+    );
 }
 
 function putSoftwareProductAction(id, action, version) {
-       return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {action: action});
+    return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {
+        action: action
+    });
 }
 
 function fetchSoftwareProductList() {
-       return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`
+    );
 }
 
 function fetchArchivedSoftwareProductList() {
-       return RestAPIUtil.fetch(`${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`
+    );
 }
 
 function fetchFinalizedSoftwareProductList() {
-       return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`
+    );
 }
 
 function fetchSoftwareProduct(vspId, version) {
-       return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`);
+    return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`);
 }
 
 function fetchSoftwareProductQuestionnaire(vspId, version) {
-       return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}${vspId}/versions/${version.id}/questionnaire`
+    );
 }
 
-function updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version) {
-       return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`, heatCandidate);
+function updateSoftwareProductHeatCandidate(
+    softwareProductId,
+    heatCandidate,
+    version
+) {
+    return RestAPIUtil.put(
+        `${baseUrl()}${softwareProductId}/versions/${
+            version.id
+        }/orchestration-template-candidate/manifest`,
+        heatCandidate
+    );
 }
 function validateHeatCandidate(softwareProductId, version) {
-       return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/process`);
+    return RestAPIUtil.put(
+        `${baseUrl()}${softwareProductId}/versions/${
+            version.id
+        }/orchestration-template-candidate/process`
+    );
 }
 
-function fetchOrchestrationTemplateCandidate(softwareProductId, version, ) {
-       return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate`, {dataType: 'binary'});
+function fetchOrchestrationTemplateCandidate(softwareProductId, version) {
+    return RestAPIUtil.fetch(
+        `${baseUrl()}${softwareProductId}/versions/${
+            version.id
+        }/orchestration-template-candidate`,
+        { dataType: 'binary' }
+    );
 }
 
 function abortValidationProcess(softwareProductId, version) {
-       return RestAPIUtil.destroy(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate`);
+    return RestAPIUtil.destroy(
+        `${baseUrl()}${softwareProductId}/versions/${
+            version.id
+        }/orchestration-template-candidate`
+    );
 }
 
 function objToString(obj) {
-       let str = '';
-       if (obj instanceof Array) {
-               obj.forEach((item) => {
-                       str += objToString(item) + '\n';
-               });
-       }
-       else {
-               for (let p in obj) {
-                       if (obj.hasOwnProperty(p)) {
-                               str += obj[p] + '\n';
-                       }
-               }
-       }
-       return str.replace(/\n$/, '');
+    let str = '';
+    if (obj instanceof Array) {
+        obj.forEach(item => {
+            str += objToString(item) + '\n';
+        });
+    } else {
+        for (let p in obj) {
+            if (obj.hasOwnProperty(p)) {
+                str += obj[p] + '\n';
+            }
+        }
+    }
+    return str.replace(/\n$/, '');
 }
 
 function parseUploadErrorMsg(error) {
-       let message = '';
-       for (let key in error) {
-               if (error.hasOwnProperty(key)) {
-                       message += objToString(error[key]) + '\n';
-               }
-       }
-       return message.replace(/\n$/, '');
+    let message = '';
+    for (let key in error) {
+        if (error.hasOwnProperty(key)) {
+            message += objToString(error[key]) + '\n';
+        }
+    }
+    return message.replace(/\n$/, '');
 }
 
 function fetchSoftwareProductCategories(dispatch) {
-       let handleResponse = response => dispatch({
-               type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED,
-               softwareProductCategories: response
-       });
-       return RestAPIUtil.fetch(softwareProductCategoriesUrl())
-               .then(handleResponse)
-               .catch(() => handleResponse(null));
+    let handleResponse = response =>
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED,
+            softwareProductCategories: response
+        });
+    return RestAPIUtil.fetch(softwareProductCategoriesUrl())
+        .then(handleResponse)
+        .catch(() => handleResponse(null));
 }
 
-function loadLicensingData(dispatch, {licenseModelId, licensingVersion}) {
-       return ItemsHelper.fetchVersion({itemId: licenseModelId, versionId: licensingVersion}).then(() => {
-               return Promise.all([
-                       LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: {id: licensingVersion}}),
-                       FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: {id: licensingVersion}})
-               ]);
-       });
+function loadLicensingData(dispatch, { licenseModelId, licensingVersion }) {
+    return ItemsHelper.fetchVersion({
+        itemId: licenseModelId,
+        versionId: licensingVersion
+    }).then(() => {
+        return Promise.all([
+            LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
+                licenseModelId,
+                version: { id: licensingVersion }
+            }),
+            FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+                licenseModelId,
+                version: { id: licensingVersion }
+            })
+        ]);
+    });
 }
 
 function getExpandedItemsId(items, itemIdToToggle) {
-       for (let i = 0; i < items.length; i++) {
-               if (items[i].id === itemIdToToggle) {
-                       if (items[i].expanded) {
-                               return {};
-                       }
-                       else {
-                               return {[itemIdToToggle]: true};
-                       }
-               }
-               else if (items[i].items && items[i].items.length > 0) {
-                       let mapOfExpandedIds = getExpandedItemsId(items[i].items, itemIdToToggle);
-                       if (mapOfExpandedIds !== false) {
-                               mapOfExpandedIds[items[i].id] = true;
-                               return mapOfExpandedIds;
-                       }
-               }
-       }
-       return false;
+    for (let i = 0; i < items.length; i++) {
+        if (items[i].id === itemIdToToggle) {
+            if (items[i].expanded) {
+                return {};
+            } else {
+                return { [itemIdToToggle]: true };
+            }
+        } else if (items[i].items && items[i].items.length > 0) {
+            let mapOfExpandedIds = getExpandedItemsId(
+                items[i].items,
+                itemIdToToggle
+            );
+            if (mapOfExpandedIds !== false) {
+                mapOfExpandedIds[items[i].id] = true;
+                return mapOfExpandedIds;
+            }
+        }
+    }
+    return false;
 }
 
 function migrateSoftwareProduct(vspId, version) {
-       return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`);
+    return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`);
 }
 
-
-
 const SoftwareProductActionHelper = {
-
-       fetchFinalizedSoftwareProductList(dispatch) {
-               return fetchFinalizedSoftwareProductList().then(response => dispatch({
-                       type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED,
-                       response
-               }));
-       },
-
-       fetchArchivedSoftwareProductList(dispatch) {
-               return fetchArchivedSoftwareProductList().then(response => dispatch({
-                       type: actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED,
-                       response
-               }));
-       },
-
-       loadSoftwareProductAssociatedData(dispatch) {
-               fetchSoftwareProductCategories(dispatch);
-               LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
-       },
-
-       loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion}) {
-               SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
-               if (licensingVersion) {
-                       return loadLicensingData(dispatch, {licenseModelId, licensingVersion});
-               }
-               return Promise.resolve();
-       },
-
-       fetchSoftwareProductList(dispatch) {
-               return fetchSoftwareProductList().then(response => dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED,
-                       response
-               }));
-       },
-
-       loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version}){
-               return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`).then(response => dispatch({
-                       type: HeatSetupActions.MANIFEST_LOADED,
-                       response
-               }));
-       },
-
-       loadLicensingVersionsList(dispatch, {licenseModelId}){
-               return ItemsHelper.fetchVersions({itemId: licenseModelId}).then(response => {
-                       dispatch({
-                               type: actionTypes.LOAD_LICENSING_VERSIONS_LIST,
-                               licensingVersionsList: response.results
-                       });
-               });
-       },
-       updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}){
-               return updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version);
-       },
-
-       processAndValidateHeatCandidate(dispatch, {softwareProductId, version}){
-               return validateHeatCandidate(softwareProductId, version).then(response => {
-                       if (response.status === 'Success') {
-                               SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
-                               SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
-                       } else {
-                               SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
-                       }
-               });
-       },
-
-       uploadFile(dispatch, {softwareProductId, formData, failedNotificationTitle, version}) {
-               dispatch({
-                       type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
-                       payload: {}
-               });
-
-               Promise.resolve()
-                       .then(() => uploadFile(softwareProductId, formData, version))
-                       .then(response => {
-                               if (response.status === 'Success') {
-                                       dispatch({
-                                               type: commonActionTypes.DATA_CHANGED,
-                                               deltaData: {onboardingOrigin: response.onboardingOrigin},
-                                               formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
-                                       });
-                                       switch(response.onboardingOrigin){
-                                               case onboardingOriginTypes.ZIP:
-                                                       ScreensHelper.loadScreen(dispatch, {
-                                                               screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                                               props: {softwareProductId, version}
-                                                       });
-                                                       dispatch({
-                                                               type: actionTypes.CANDIDATE_IN_PROCESS,
-                                                               inProcess: true
-                                                       });
-                                                       break;
-                                               case onboardingOriginTypes.CSAR:
-                                                       ScreensHelper.loadScreen(dispatch, {
-                                                               screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                                               props: {softwareProductId, version}
-                                                       });
-                                                       break;
-                                       }
-                               }
-                               else {
-                                       throw new Error(parseUploadErrorMsg(response.errors));
-                               }
-                       })
-                       .catch(error => {
-                               dispatch({
-                                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                                       data: {
-                                               title: failedNotificationTitle,
-                                               msg: error.message || (error.responseJSON && error.responseJSON.message)
-                                       }
-                               });
-                       });
-       },
-
-       downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}){
-               let p = isReadOnlyMode ? Promise.resolve() : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {
-                       softwareProductId,
-                       heatCandidate,
-                       version});
-               p.then(() => {
-                       fetchOrchestrationTemplateCandidate(softwareProductId, version)
-                               .then((response) => {
-                                       showFileSaveDialog({
-                                               blob: response.blob,
-                                               headers: response.headers,
-                                               defaultFilename: 'HEAT_file.zip',
-                                               addTimestamp: true
-                                       });
-                               });
-               }, null/* do not download if data was not saved correctly*/);
-       },
-
-       hideUploadConfirm (dispatch) {
-               dispatch({
-                       type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION
-               });
-       },
-       updateSoftwareProduct(dispatch, {softwareProduct, version, qdata}) {
-               return Promise.all([
-                       SoftwareProductActionHelper.updateSoftwareProductData(dispatch, {softwareProduct, version}).then(
-                               () => dispatch({
-                                       type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT,
-                                       payload: {softwareProduct}
-                               })
-                       ),
-                       SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(dispatch, {
-                               softwareProductId: softwareProduct.id,
-                               qdata,
-                               version
-                       })
-               ]);
-       },
-
-       updateSoftwareProductData(dispatch, {softwareProduct, version}) {
-               return putSoftwareProduct({softwareProduct, version});
-       },
-
-       updateSoftwareProductQuestionnaire(dispatch, {softwareProductId, qdata, version}) {
-               return putSoftwareProductQuestionnaire(softwareProductId, qdata, version);
-       },
-
-       softwareProductEditorDataChanged(dispatch, {deltaData}) {
-               dispatch({
-                       type: actionTypes.softwareProductEditor.DATA_CHANGED,
-                       deltaData
-               });
-       },
-
-       softwareProductQuestionnaireUpdate(dispatch, {data}) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE,
-                       payload: {qdata: data}
-               });
-       },
-
-       softwareProductEditorVendorChanged(dispatch, {deltaData, formName}) {
-               if (deltaData.licensingVersion){
-                       return loadLicensingData(dispatch, {licenseModelId: deltaData.vendorId, licensingVersion: deltaData.licensingVersion}).then(() => {
-                               ValidationHelper.dataChanged(dispatch, {deltaData, formName});
-                               return Promise.resolve();
-                       });
-               } else if (deltaData.vendorId) {
-                       ValidationHelper.dataChanged(dispatch, {deltaData, formName});
-                       return SoftwareProductActionHelper.loadLicensingVersionsList(dispatch, {
-                               licenseModelId: deltaData.vendorId
-                       }).then( () =>
-                               OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch)
-                       );
-               } else {
-                       ValidationHelper.dataChanged(dispatch, {deltaData, formName});
-
-                       dispatch({
-                               type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
-                               response: {results: []}
-                       });
-
-                       dispatch({
-                               type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
-                               response: {results: []}
-                       });
-               }
-
-       },
-
-       setIsValidityData(dispatch, {isValidityData}) {
-               dispatch({
-                       type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED,
-                       isValidityData
-               });
-       },
-
-       fetchSoftwareProduct(dispatch, {softwareProductId, version}) {
-               return Promise.all([
-                       fetchSoftwareProduct(softwareProductId, version).then(response => {
-                               dispatch({
-                                       type: actionTypes.SOFTWARE_PRODUCT_LOADED,
-                                       response
-                               });
-                               return response;
-                       }),
-                       fetchSoftwareProductQuestionnaire(softwareProductId, version).then(response => {
-                               ValidationHelper.qDataLoaded(dispatch, {response: {qdata: response.data ? JSON.parse(response.data) : {},
-                                       qschema: JSON.parse(response.schema)}, qName: PRODUCT_QUESTIONNAIRE});
-                       })
-               ]);
-       },
-
-       manageSubmitAction(dispatch, {softwareProductId, version, isDirty}) {
-               if (isDirty) {
-                       const onCommit = comment => {
-                               return this.performVCAction(dispatch, {softwareProductId, action: VersionControllerActionsEnum.COMMIT, version, comment}).then(() => {
-                                       return this.performSubmitAction(dispatch, {softwareProductId, version});
-                               });
-                       };
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                               data: {
-                                       modalComponentName: modalContentMapper.COMMIT_COMMENT,
-                                       modalComponentProps: {
-                                               onCommit,
-                                               type: CommitModalType.COMMIT_SUBMIT
-                                       },
-                                       title: i18n('Commit & Submit')
-                               }
-                       });
-                       return Promise.resolve(version);
-               }
-               return this.performSubmitAction(dispatch, {softwareProductId, version});
-       },
-
-       performSubmitAction(dispatch, {softwareProductId, version}) {
-               return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.SUBMIT, version).then(() => {
-                       return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.CREATE_PACKAGE, version).then(() => {
-                               return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id}).then(updatedVersion => {
-                                       dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
-                                               data: {
-                                                       title: i18n('Submit Succeeded'),
-                                                       msg: i18n('This software product successfully submitted'),
-                                                       cancelButtonText: i18n('OK'),
-                                                       timeout: 2000
-                                               }
-                                       });
-                                       versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId});
-                                       return Promise.resolve(updatedVersion);
-                               });
-                       });
-               }, error =>
-               {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                               data: {
-                                       modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE,
-                                       title: i18n('Submit Failed'),
-                                       modalComponentProps: {
-                                               validationResponse: error.responseJSON
-                                       },
-                                       cancelButtonText: i18n('OK')
-                               }
-                       });
-                       return Promise.reject(error.responseJSON);
-               });
-       },
-
-       performVCAction(dispatch, {softwareProductId, action, version, comment}) {
-               return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({inMerge, isDirty, updatedVersion}) => {
-                       if ((updatedVersion.status === catalogItemStatuses.CERTIFIED || updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED) &&
-                                        (action === VersionControllerActionsEnum.COMMIT || action === VersionControllerActionsEnum.SYNC)) {
-                               versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId});
-                               const msg = updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED ? i18n('Item was Archived') : i18n('Item version already Certified');
-                               dispatch({
-                                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                                       data: {
-                                               title: i18n('Commit error'),
-                                               msg,
-                                               cancelButtonText: i18n('Cancel')
-                                       }
-                               });
-                               return Promise.resolve(updatedVersion);
-                       }
-                       if (!inMerge) {
-                               if (action === VersionControllerActionsEnum.SUBMIT) {
-                                       return this.manageSubmitAction(dispatch, {softwareProductId, version, isDirty});
-                               }
-                               else {
-                                       let isCallActionValid = action !== VersionControllerActionsEnum.COMMIT || isDirty;
-                                       if(isCallActionValid) {
-                                               return  ItemsHelper.performVCAction({itemId: softwareProductId, action, version, comment}).then(() => {
-                                                       versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: softwareProductId});
-                                                       if (action === VersionControllerActionsEnum.SYNC) {
-                                                               return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({updatedVersion}) => {
-                                                                       return Promise.resolve(updatedVersion);
-                                                               });
-                                                       } else {
-                                                               return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id});
-                                                       }
-                                               });
-                                       }
-                                       else {
-                                               dispatch({
-                                                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                                                       data: {
-                                                               title: i18n('Commit Failed'),
-                                                               msg: i18n('There is nothing to commit')
-                                                       }
-                                               });
-                                       }
-                               }
-                       }
-               });
-       },
-
-       toggleNavigationItems(dispatch, {items, itemIdToExpand}) {
-               let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand);
-               dispatch({
-                       type: actionTypes.TOGGLE_NAVIGATION_ITEM,
-                       mapOfExpandedIds
-               });
-       },
-
-       /** for the next verision */
-       addComponent(dispatch, {softwareProductId, modalClassName, version}) {
-               SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch);
-               dispatch({
-                       type: componentActionTypes.COMPONENT_CREATE_OPEN
-               });
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.COMPONENT_CREATION,
-                               modalComponentProps: {softwareProductId, version},
-                               modalClassName,
-                               title: 'Create Virtual Function Component'
-                       }
-               });
-       },
-
-       migrateSoftwareProduct(dispatch, {softwareProduct}) {
-               let {id: softwareProductId, version} = softwareProduct;
-               const  newVer = version.id;
-               migrateSoftwareProduct(softwareProductId, version).then(() => ScreensHelper.loadScreen(dispatch, {
-                       screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                       props: {softwareProductId, version: {id: newVer, label: newVer}}
-               }));
-       },
-
-       abortCandidateValidation(dispatch, {softwareProductId, version}) {              
-               return abortValidationProcess(softwareProductId, version);
-       }
-
+    fetchFinalizedSoftwareProductList(dispatch) {
+        return fetchFinalizedSoftwareProductList().then(response =>
+            dispatch({
+                type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED,
+                response
+            })
+        );
+    },
+
+    fetchArchivedSoftwareProductList(dispatch) {
+        return fetchArchivedSoftwareProductList().then(response =>
+            dispatch({
+                type: actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED,
+                response
+            })
+        );
+    },
+
+    loadSoftwareProductAssociatedData(dispatch) {
+        fetchSoftwareProductCategories(dispatch);
+        LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
+    },
+
+    loadSoftwareProductDetailsData(
+        dispatch,
+        { licenseModelId, licensingVersion }
+    ) {
+        SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
+        if (licensingVersion) {
+            return loadLicensingData(dispatch, {
+                licenseModelId,
+                licensingVersion
+            });
+        }
+        return Promise.resolve();
+    },
+
+    fetchSoftwareProductList(dispatch) {
+        return fetchSoftwareProductList().then(response =>
+            dispatch({
+                type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED,
+                response
+            })
+        );
+    },
+
+    loadSoftwareProductHeatCandidate(dispatch, { softwareProductId, version }) {
+        return RestAPIUtil.fetch(
+            `${baseUrl()}${softwareProductId}/versions/${
+                version.id
+            }/orchestration-template-candidate/manifest`
+        ).then(response =>
+            dispatch({
+                type: HeatSetupActions.MANIFEST_LOADED,
+                response
+            })
+        );
+    },
+
+    loadLicensingVersionsList(dispatch, { licenseModelId }) {
+        return ItemsHelper.fetchVersions({ itemId: licenseModelId }).then(
+            response => {
+                dispatch({
+                    type: actionTypes.LOAD_LICENSING_VERSIONS_LIST,
+                    licensingVersionsList: response.results
+                });
+            }
+        );
+    },
+    updateSoftwareProductHeatCandidate(
+        dispatch,
+        { softwareProductId, heatCandidate, version }
+    ) {
+        return updateSoftwareProductHeatCandidate(
+            softwareProductId,
+            heatCandidate,
+            version
+        );
+    },
+
+    processAndValidateHeatCandidate(dispatch, { softwareProductId, version }) {
+        return validateHeatCandidate(softwareProductId, version).then(
+            response => {
+                if (response.status === 'Success') {
+                    SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+                        dispatch,
+                        { softwareProductId, version }
+                    );
+                    SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
+                        softwareProductId,
+                        version
+                    });
+                } else {
+                    SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
+                        softwareProductId,
+                        version
+                    });
+                }
+            }
+        );
+    },
+
+    uploadFile(
+        dispatch,
+        { softwareProductId, formData, failedNotificationTitle, version }
+    ) {
+        dispatch({
+            type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
+            payload: {}
+        });
+
+        Promise.resolve()
+            .then(() => uploadFile(softwareProductId, formData, version))
+            .then(response => {
+                if (response.status === 'Success') {
+                    dispatch({
+                        type: commonActionTypes.DATA_CHANGED,
+                        deltaData: {
+                            onboardingOrigin: response.onboardingOrigin
+                        },
+                        formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+                    });
+                    switch (response.onboardingOrigin) {
+                        case onboardingOriginTypes.ZIP:
+                            ScreensHelper.loadScreen(dispatch, {
+                                screen:
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP,
+                                screenType: screenTypes.SOFTWARE_PRODUCT,
+                                props: { softwareProductId, version }
+                            });
+                            dispatch({
+                                type: actionTypes.CANDIDATE_IN_PROCESS,
+                                inProcess: true
+                            });
+                            break;
+                        case onboardingOriginTypes.CSAR:
+                            ScreensHelper.loadScreen(dispatch, {
+                                screen:
+                                    enums.SCREEN
+                                        .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION,
+                                screenType: screenTypes.SOFTWARE_PRODUCT,
+                                props: { softwareProductId, version }
+                            });
+                            break;
+                    }
+                } else {
+                    throw new Error(parseUploadErrorMsg(response.errors));
+                }
+            })
+            .catch(error => {
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                    data: {
+                        title: failedNotificationTitle,
+                        msg:
+                            error.message ||
+                            (error.responseJSON && error.responseJSON.message)
+                    }
+                });
+            });
+    },
+
+    downloadHeatFile(
+        dispatch,
+        { softwareProductId, heatCandidate, isReadOnlyMode, version }
+    ) {
+        let p = isReadOnlyMode
+            ? Promise.resolve()
+            : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(
+                  dispatch,
+                  {
+                      softwareProductId,
+                      heatCandidate,
+                      version
+                  }
+              );
+        p.then(() => {
+            fetchOrchestrationTemplateCandidate(
+                softwareProductId,
+                version
+            ).then(response => {
+                showFileSaveDialog({
+                    blob: response.blob,
+                    headers: response.headers,
+                    defaultFilename: 'HEAT_file.zip',
+                    addTimestamp: true
+                });
+            });
+        }, null /* do not download if data was not saved correctly*/);
+    },
+
+    hideUploadConfirm(dispatch) {
+        dispatch({
+            type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION
+        });
+    },
+    updateSoftwareProduct(dispatch, { softwareProduct, version, qdata }) {
+        return Promise.all([
+            SoftwareProductActionHelper.updateSoftwareProductData(dispatch, {
+                softwareProduct,
+                version
+            }).then(() =>
+                dispatch({
+                    type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT,
+                    payload: { softwareProduct }
+                })
+            ),
+            SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId: softwareProduct.id,
+                    qdata,
+                    version
+                }
+            )
+        ]);
+    },
+
+    updateSoftwareProductData(dispatch, { softwareProduct, version }) {
+        return putSoftwareProduct({ softwareProduct, version });
+    },
+
+    updateSoftwareProductQuestionnaire(
+        dispatch,
+        { softwareProductId, qdata, version }
+    ) {
+        return putSoftwareProductQuestionnaire(
+            softwareProductId,
+            qdata,
+            version
+        );
+    },
+
+    softwareProductEditorDataChanged(dispatch, { deltaData }) {
+        dispatch({
+            type: actionTypes.softwareProductEditor.DATA_CHANGED,
+            deltaData
+        });
+    },
+
+    softwareProductQuestionnaireUpdate(dispatch, { data }) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE,
+            payload: { qdata: data }
+        });
+    },
+
+    softwareProductEditorVendorChanged(dispatch, { deltaData, formName }) {
+        if (deltaData.licensingVersion) {
+            return loadLicensingData(dispatch, {
+                licenseModelId: deltaData.vendorId,
+                licensingVersion: deltaData.licensingVersion
+            }).then(() => {
+                ValidationHelper.dataChanged(dispatch, { deltaData, formName });
+                return Promise.resolve();
+            });
+        } else if (deltaData.vendorId) {
+            ValidationHelper.dataChanged(dispatch, { deltaData, formName });
+            return SoftwareProductActionHelper.loadLicensingVersionsList(
+                dispatch,
+                {
+                    licenseModelId: deltaData.vendorId
+                }
+            ).then(() =>
+                OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch)
+            );
+        } else {
+            ValidationHelper.dataChanged(dispatch, { deltaData, formName });
+
+            dispatch({
+                type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
+                response: { results: [] }
+            });
+
+            dispatch({
+                type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
+                response: { results: [] }
+            });
+        }
+    },
+
+    setIsValidityData(dispatch, { isValidityData }) {
+        dispatch({
+            type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED,
+            isValidityData
+        });
+    },
+
+    fetchSoftwareProduct(dispatch, { softwareProductId, version }) {
+        return Promise.all([
+            fetchSoftwareProduct(softwareProductId, version).then(response => {
+                dispatch({
+                    type: actionTypes.SOFTWARE_PRODUCT_LOADED,
+                    response
+                });
+                return response;
+            }),
+            fetchSoftwareProductQuestionnaire(softwareProductId, version).then(
+                response => {
+                    ValidationHelper.qDataLoaded(dispatch, {
+                        response: {
+                            qdata: response.data
+                                ? JSON.parse(response.data)
+                                : {},
+                            qschema: JSON.parse(response.schema)
+                        },
+                        qName: PRODUCT_QUESTIONNAIRE
+                    });
+                }
+            )
+        ]);
+    },
+
+    manageSubmitAction(dispatch, { softwareProductId, version, isDirty }) {
+        if (isDirty) {
+            const onCommit = comment => {
+                return this.performVCAction(dispatch, {
+                    softwareProductId,
+                    action: VersionControllerActionsEnum.COMMIT,
+                    version,
+                    comment
+                }).then(() => {
+                    return this.performSubmitAction(dispatch, {
+                        softwareProductId,
+                        version
+                    });
+                });
+            };
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    modalComponentName: modalContentMapper.COMMIT_COMMENT,
+                    modalComponentProps: {
+                        onCommit,
+                        type: CommitModalType.COMMIT_SUBMIT
+                    },
+                    title: i18n('Commit & Submit')
+                }
+            });
+            return Promise.resolve(version);
+        }
+        return this.performSubmitAction(dispatch, {
+            softwareProductId,
+            version
+        });
+    },
+
+    performSubmitAction(dispatch, { softwareProductId, version }) {
+        return putSoftwareProductAction(
+            softwareProductId,
+            VersionControllerActionsEnum.SUBMIT,
+            version
+        ).then(
+            () => {
+                return putSoftwareProductAction(
+                    softwareProductId,
+                    VersionControllerActionsEnum.CREATE_PACKAGE,
+                    version
+                ).then(() => {
+                    return ItemsHelper.checkItemStatus(dispatch, {
+                        itemId: softwareProductId,
+                        versionId: version.id
+                    }).then(updatedVersion => {
+                        dispatch({
+                            type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
+                            data: {
+                                title: i18n('Submit Succeeded'),
+                                msg: i18n(
+                                    'This software product successfully submitted'
+                                ),
+                                cancelButtonText: i18n('OK'),
+                                timeout: 2000
+                            }
+                        });
+                        versionPageActionHelper.fetchVersions(dispatch, {
+                            itemType: itemTypes.SOFTWARE_PRODUCT,
+                            itemId: softwareProductId
+                        });
+                        return Promise.resolve(updatedVersion);
+                    });
+                });
+            },
+            error => {
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                    data: {
+                        modalComponentName:
+                            modalContentMapper.SUMBIT_ERROR_RESPONSE,
+                        title: i18n('Submit Failed'),
+                        modalComponentProps: {
+                            validationResponse: error.responseJSON
+                        },
+                        cancelButtonText: i18n('OK')
+                    }
+                });
+                return Promise.reject(error.responseJSON);
+            }
+        );
+    },
+
+    performVCAction(dispatch, { softwareProductId, action, version, comment }) {
+        return MergeEditorActionHelper.analyzeSyncResult(dispatch, {
+            itemId: softwareProductId,
+            version
+        }).then(({ inMerge, isDirty, updatedVersion }) => {
+            if (
+                (updatedVersion.status === catalogItemStatuses.CERTIFIED ||
+                    updatedVersion.archivedStatus ===
+                        catalogItemStatuses.ARCHIVED) &&
+                (action === VersionControllerActionsEnum.COMMIT ||
+                    action === VersionControllerActionsEnum.SYNC)
+            ) {
+                versionPageActionHelper.fetchVersions(dispatch, {
+                    itemType: itemTypes.SOFTWARE_PRODUCT,
+                    itemId: softwareProductId
+                });
+                const msg =
+                    updatedVersion.archivedStatus ===
+                    catalogItemStatuses.ARCHIVED
+                        ? i18n('Item was Archived')
+                        : i18n('Item version already Certified');
+                dispatch({
+                    type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                    data: {
+                        title: i18n('Commit error'),
+                        msg,
+                        cancelButtonText: i18n('Cancel')
+                    }
+                });
+                return Promise.resolve(updatedVersion);
+            }
+            if (!inMerge) {
+                if (action === VersionControllerActionsEnum.SUBMIT) {
+                    return this.manageSubmitAction(dispatch, {
+                        softwareProductId,
+                        version,
+                        isDirty
+                    });
+                } else {
+                    let isCallActionValid =
+                        action !== VersionControllerActionsEnum.COMMIT ||
+                        isDirty;
+                    if (isCallActionValid) {
+                        return ItemsHelper.performVCAction({
+                            itemId: softwareProductId,
+                            action,
+                            version,
+                            comment
+                        }).then(() => {
+                            versionPageActionHelper.fetchVersions(dispatch, {
+                                itemType: itemTypes.LICENSE_MODEL,
+                                itemId: softwareProductId
+                            });
+                            if (action === VersionControllerActionsEnum.SYNC) {
+                                return MergeEditorActionHelper.analyzeSyncResult(
+                                    dispatch,
+                                    { itemId: softwareProductId, version }
+                                ).then(({ updatedVersion }) => {
+                                    return Promise.resolve(updatedVersion);
+                                });
+                            } else {
+                                return ItemsHelper.checkItemStatus(dispatch, {
+                                    itemId: softwareProductId,
+                                    versionId: version.id
+                                });
+                            }
+                        });
+                    } else {
+                        dispatch({
+                            type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                            data: {
+                                title: i18n('Commit Failed'),
+                                msg: i18n('There is nothing to commit')
+                            }
+                        });
+                    }
+                }
+            }
+        });
+    },
+
+    toggleNavigationItems(dispatch, { items, itemIdToExpand }) {
+        let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand);
+        dispatch({
+            type: actionTypes.TOGGLE_NAVIGATION_ITEM,
+            mapOfExpandedIds
+        });
+    },
+
+    /** for the next verision */
+    addComponent(dispatch, { softwareProductId, modalClassName, version }) {
+        SoftwareProductComponentsActionHelper.clearComponentCreationData(
+            dispatch
+        );
+        dispatch({
+            type: componentActionTypes.COMPONENT_CREATE_OPEN
+        });
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName: modalContentMapper.COMPONENT_CREATION,
+                modalComponentProps: { softwareProductId, version },
+                modalClassName,
+                title: 'Create Virtual Function Component'
+            }
+        });
+    },
+
+    migrateSoftwareProduct(dispatch, { softwareProduct }) {
+        let { id: softwareProductId, version } = softwareProduct;
+        const newVer = version.id;
+        migrateSoftwareProduct(softwareProductId, version).then(() =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: {
+                    softwareProductId,
+                    version: { id: newVer, label: newVer }
+                }
+            })
+        );
+    },
+
+    abortCandidateValidation(dispatch, { softwareProductId, version }) {
+        return abortValidationProcess(softwareProductId, version);
+    }
 };
 
 export default SoftwareProductActionHelper;
index 9b14741..d1ba947 100644 (file)
  * permissions and limitations under the License.
  */
 export default {
-
-       getCurrentCategoryOfSubCategory(selectedSubCategory, softwareProductCategories) {
-               let category, subCategory;
-               for (var i = 0; i < softwareProductCategories.length; i++) {
-                       let {subcategories = []} = softwareProductCategories[i];
-                       subCategory = subcategories.find(sub => sub.uniqueId === selectedSubCategory);
-                       if (subCategory) {
-                               category = softwareProductCategories[i].uniqueId;
-                               break;
-                       }
-               }
-               return category;
-       }
+    getCurrentCategoryOfSubCategory(
+        selectedSubCategory,
+        softwareProductCategories
+    ) {
+        let category, subCategory;
+        for (var i = 0; i < softwareProductCategories.length; i++) {
+            let { subcategories = [] } = softwareProductCategories[i];
+            subCategory = subcategories.find(
+                sub => sub.uniqueId === selectedSubCategory
+            );
+            if (subCategory) {
+                category = softwareProductCategories[i].uniqueId;
+                break;
+            }
+        }
+        return category;
+    }
 };
index d33eb82..711bbf8 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       SOFTWARE_PRODUCT_LOADED: null,
-       SOFTWARE_PRODUCT_LIST_LOADED: null,
-       ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: null,
-       FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: null,
-       SOFTWARE_PRODUCT_LIST_EDIT: null,
-       SOFTWARE_PRODUCT_CATEGORIES_LOADED: null,
-       SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE: null,
-       LOAD_LICENSING_VERSIONS_LIST: null,
-       TOGGLE_NAVIGATION_ITEM: null,
-       CANDIDATE_IN_PROCESS: null,
-
-       softwareProductEditor: {
-               OPEN: null,
-               CLOSE: null,
-               DATA_CHANGED: null,
-               IS_VALIDITY_DATA_CHANGED: null
-       }
+    SOFTWARE_PRODUCT_LOADED: null,
+    SOFTWARE_PRODUCT_LIST_LOADED: null,
+    ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: null,
+    FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: null,
+    SOFTWARE_PRODUCT_LIST_EDIT: null,
+    SOFTWARE_PRODUCT_CATEGORIES_LOADED: null,
+    SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE: null,
+    LOAD_LICENSING_VERSIONS_LIST: null,
+    TOGGLE_NAVIGATION_ITEM: null,
+    CANDIDATE_IN_PROCESS: null,
+
+    softwareProductEditor: {
+        OPEN: null,
+        CLOSE: null,
+        DATA_CHANGED: null,
+        IS_VALIDITY_DATA_CHANGED: null
+    }
 });
 
-
-
 export const onboardingMethod = {
-       MANUAL: 'Manual',
-       NETWORK_PACKAGE: 'NetworkPackage'
+    MANUAL: 'Manual',
+    NETWORK_PACKAGE: 'NetworkPackage'
 };
 
 export const onboardingOriginTypes = {
-       NONE: 'none',
-       ZIP: 'zip',
-       CSAR: 'csar'
+    NONE: 'none',
+    ZIP: 'zip',
+    CSAR: 'csar'
 };
 
 export const forms = keyMirror({
-       VENDOR_SOFTWARE_PRODUCT_DETAILS: 'vendor-software-product-details',
+    VENDOR_SOFTWARE_PRODUCT_DETAILS: 'vendor-software-product-details'
 });
 
 export const PRODUCT_QUESTIONNAIRE = 'product';
-
index 31be338..f52153a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductConstants.js';
+import { actionTypes } from './SoftwareProductConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.SOFTWARE_PRODUCT_LIST_LOADED:
-                       return [...action.response.results];
-               case actionTypes.SOFTWARE_PRODUCT_LIST_EDIT:
-                       const indexForEdit = state.findIndex(vsp => vsp.id === action.payload.softwareProduct.id);
-                       return [...state.slice(0, indexForEdit), action.payload.softwareProduct, ...state.slice(indexForEdit + 1)];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.SOFTWARE_PRODUCT_LIST_LOADED:
+            return [...action.response.results];
+        case actionTypes.SOFTWARE_PRODUCT_LIST_EDIT:
+            const indexForEdit = state.findIndex(
+                vsp => vsp.id === action.payload.softwareProduct.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.payload.softwareProduct,
+                ...state.slice(indexForEdit + 1)
+            ];
+        default:
+            return state;
+    }
 };
index d7a6c2e..f3de517 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {combineReducers} from 'redux';
-import {actionTypes, PRODUCT_QUESTIONNAIRE} from './SoftwareProductConstants.js';
+import { combineReducers } from 'redux';
+import {
+    actionTypes,
+    PRODUCT_QUESTIONNAIRE
+} from './SoftwareProductConstants.js';
 import SoftwareProductAttachmentsReducer from './attachments/SoftwareProductAttachmentsReducer.js';
 import HeatValidationReducer from './attachments/validation/HeatValidationReducer.js';
 import HeatSetupReducer from './attachments/setup/HeatSetupReducer.js';
-import {actionTypes as heatSetupActionTypes} from './attachments/setup/HeatSetupConstants.js';
+import { actionTypes as heatSetupActionTypes } from './attachments/setup/HeatSetupConstants.js';
 import SoftwareProductCreationReducer from './creation/SoftwareProductCreationReducer.js';
 import SoftwareProductDetailsReducer from './details/SoftwareProductDetailsReducer.js';
 import SoftwareProductProcessesListReducer from './processes/SoftwareProductProcessesListReducer.js';
@@ -28,10 +31,10 @@ import SoftwareProductDeploymentEditorReducer from './deployment/editor/Software
 import SoftwareProductNetworksListReducer from './networks/SoftwareProductNetworksListReducer.js';
 import SoftwareProductComponentsListReducer from './components/SoftwareProductComponentsListReducer.js';
 import SoftwareProductComponentEditorReducer from './components/SoftwareProductComponentEditorReducer.js';
-import  {actionTypes as processesActionTypes} from './processes/SoftwareProductProcessesConstants.js';
-import SoftwareProductComponentProcessesListReducer  from './components/processes/SoftwareProductComponentProcessesListReducer.js';
+import { actionTypes as processesActionTypes } from './processes/SoftwareProductProcessesConstants.js';
+import SoftwareProductComponentProcessesListReducer from './components/processes/SoftwareProductComponentProcessesListReducer.js';
 import SoftwareProductComponentProcessesEditorReducer from './components/processes/SoftwareProductComponentProcessesEditorReducer.js';
-import  {actionTypes as componentProcessesActionTypes} from './components/processes/SoftwareProductComponentProcessesConstants.js';
+import { actionTypes as componentProcessesActionTypes } from './components/processes/SoftwareProductComponentProcessesConstants.js';
 import SoftwareProductComponentsNICListReducer from './components/network/SoftwareProductComponentsNICListReducer.js';
 import SoftwareProductComponentsNICEditorReducer from './components/network/SoftwareProductComponentsNICEditorReducer.js';
 import SoftwareProductComponentsImageListReducer from './components/images/SoftwareProductComponentsImageListReducer.js';
@@ -40,63 +43,112 @@ import SoftwareProductComponentsNICCreationReducer from './components/network/NI
 import SoftwareProductComponentsMonitoringReducer from './components/monitoring/SoftwareProductComponentsMonitoringReducer.js';
 import SoftwareProductComponentsComputeFlavorListReducer from './components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js';
 import SoftwareProductComponentsComputeFlavorReducer from './components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js';
-import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
+import { createPlainDataReducer } from 'sdc-app/common/reducers/PlainDataReducer.js';
 import SoftwareProductDependenciesReducer from './dependencies/SoftwareProductDependenciesReducer.js';
-import {createJSONSchemaReducer, createComposedJSONSchemaReducer} from 'sdc-app/common/reducers/JSONSchemaReducer.js';
-import {COMPONENTS_QUESTIONNAIRE, COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
-import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
-import {IMAGE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js';
+import {
+    createJSONSchemaReducer,
+    createComposedJSONSchemaReducer
+} from 'sdc-app/common/reducers/JSONSchemaReducer.js';
+import {
+    COMPONENTS_QUESTIONNAIRE,
+    COMPONENTS_COMPUTE_QUESTIONNAIRE
+} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
+import { IMAGE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js';
 
 export default combineReducers({
-       softwareProductAttachments: combineReducers({
-               attachmentsDetails: SoftwareProductAttachmentsReducer,
-               heatValidation: HeatValidationReducer,
-               heatSetup: HeatSetupReducer,
-               heatSetupCache: (state = {}, action) => action.type === heatSetupActionTypes.FILL_HEAT_SETUP_CACHE ? action.payload : state
-       }),
-       softwareProductCreation: createPlainDataReducer(SoftwareProductCreationReducer),
-       softwareProductEditor: createPlainDataReducer(SoftwareProductDetailsReducer),
-       softwareProductProcesses: combineReducers({
-               processesList: SoftwareProductProcessesListReducer,
-               processesEditor: createPlainDataReducer(SoftwareProductProcessesEditorReducer),
-               processToDelete: (state = false, action) => action.type === processesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM ? action.processToDelete : state
-       }),
-       softwareProductDeployment: combineReducers({
-               deploymentFlavors: SoftwareProductDeploymentListReducer,
-               deploymentFlavorEditor: createPlainDataReducer(SoftwareProductDeploymentEditorReducer)
-       }),
-       softwareProductNetworks: combineReducers({
-               networksList: SoftwareProductNetworksListReducer
-       }),
-       softwareProductDependencies: SoftwareProductDependenciesReducer,
-       softwareProductComponents: combineReducers({
-               componentsList: SoftwareProductComponentsListReducer,
-               componentEditor: createPlainDataReducer(createComposedJSONSchemaReducer(COMPONENTS_QUESTIONNAIRE, SoftwareProductComponentEditorReducer)),
-               componentProcesses: combineReducers({
-                       processesList: SoftwareProductComponentProcessesListReducer,
-                       processesEditor: createPlainDataReducer(SoftwareProductComponentProcessesEditorReducer),
-                       processToDelete: (state = false, action) => action.type === componentProcessesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM ? action.processToDelete : state,
-               }),
-               network: combineReducers({
-                       nicList: SoftwareProductComponentsNICListReducer,
-                       nicEditor: createPlainDataReducer(createComposedJSONSchemaReducer(NIC_QUESTIONNAIRE, SoftwareProductComponentsNICEditorReducer)),
-                       nicCreation: createPlainDataReducer(SoftwareProductComponentsNICCreationReducer)
-               }),
-               images: combineReducers({
-                       imagesList: SoftwareProductComponentsImageListReducer,
-                       imageEditor: createPlainDataReducer(createComposedJSONSchemaReducer(IMAGE_QUESTIONNAIRE, SoftwareProductComponentsImageEditorReducer))
-               }),
-               computeFlavor: combineReducers({
-                       computesList: SoftwareProductComponentsComputeFlavorListReducer,
-                       computeEditor: createPlainDataReducer(createComposedJSONSchemaReducer(COMPONENTS_COMPUTE_QUESTIONNAIRE, SoftwareProductComponentsComputeFlavorReducer)),
-               }),
-               monitoring: SoftwareProductComponentsMonitoringReducer
-       }),
-       softwareProductCategories: (state = [], action) => {
-               if (action.type === actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED) {
-                       return action.softwareProductCategories;
-               }
-               return state;
-       },
-       softwareProductQuestionnaire: createJSONSchemaReducer(PRODUCT_QUESTIONNAIRE)
+    softwareProductAttachments: combineReducers({
+        attachmentsDetails: SoftwareProductAttachmentsReducer,
+        heatValidation: HeatValidationReducer,
+        heatSetup: HeatSetupReducer,
+        heatSetupCache: (state = {}, action) =>
+            action.type === heatSetupActionTypes.FILL_HEAT_SETUP_CACHE
+                ? action.payload
+                : state
+    }),
+    softwareProductCreation: createPlainDataReducer(
+        SoftwareProductCreationReducer
+    ),
+    softwareProductEditor: createPlainDataReducer(
+        SoftwareProductDetailsReducer
+    ),
+    softwareProductProcesses: combineReducers({
+        processesList: SoftwareProductProcessesListReducer,
+        processesEditor: createPlainDataReducer(
+            SoftwareProductProcessesEditorReducer
+        ),
+        processToDelete: (state = false, action) =>
+            action.type ===
+            processesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM
+                ? action.processToDelete
+                : state
+    }),
+    softwareProductDeployment: combineReducers({
+        deploymentFlavors: SoftwareProductDeploymentListReducer,
+        deploymentFlavorEditor: createPlainDataReducer(
+            SoftwareProductDeploymentEditorReducer
+        )
+    }),
+    softwareProductNetworks: combineReducers({
+        networksList: SoftwareProductNetworksListReducer
+    }),
+    softwareProductDependencies: SoftwareProductDependenciesReducer,
+    softwareProductComponents: combineReducers({
+        componentsList: SoftwareProductComponentsListReducer,
+        componentEditor: createPlainDataReducer(
+            createComposedJSONSchemaReducer(
+                COMPONENTS_QUESTIONNAIRE,
+                SoftwareProductComponentEditorReducer
+            )
+        ),
+        componentProcesses: combineReducers({
+            processesList: SoftwareProductComponentProcessesListReducer,
+            processesEditor: createPlainDataReducer(
+                SoftwareProductComponentProcessesEditorReducer
+            ),
+            processToDelete: (state = false, action) =>
+                action.type ===
+                componentProcessesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM
+                    ? action.processToDelete
+                    : state
+        }),
+        network: combineReducers({
+            nicList: SoftwareProductComponentsNICListReducer,
+            nicEditor: createPlainDataReducer(
+                createComposedJSONSchemaReducer(
+                    NIC_QUESTIONNAIRE,
+                    SoftwareProductComponentsNICEditorReducer
+                )
+            ),
+            nicCreation: createPlainDataReducer(
+                SoftwareProductComponentsNICCreationReducer
+            )
+        }),
+        images: combineReducers({
+            imagesList: SoftwareProductComponentsImageListReducer,
+            imageEditor: createPlainDataReducer(
+                createComposedJSONSchemaReducer(
+                    IMAGE_QUESTIONNAIRE,
+                    SoftwareProductComponentsImageEditorReducer
+                )
+            )
+        }),
+        computeFlavor: combineReducers({
+            computesList: SoftwareProductComponentsComputeFlavorListReducer,
+            computeEditor: createPlainDataReducer(
+                createComposedJSONSchemaReducer(
+                    COMPONENTS_COMPUTE_QUESTIONNAIRE,
+                    SoftwareProductComponentsComputeFlavorReducer
+                )
+            )
+        }),
+        monitoring: SoftwareProductComponentsMonitoringReducer
+    }),
+    softwareProductCategories: (state = [], action) => {
+        if (action.type === actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED) {
+            return action.softwareProductCategories;
+        }
+        return state;
+    },
+    softwareProductQuestionnaire: createJSONSchemaReducer(PRODUCT_QUESTIONNAIRE)
 });
index d942172..4d5887b 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 import HeatSetupActionHelper from './setup/HeatSetupActionHelper.js';
 import SoftwareProductAttachmentsView from './SoftwareProductAttachmentsView.jsx';
-import {errorLevels} from 'sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js';
+import { errorLevels } from 'sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js';
 import HeatSetup from './setup/HeatSetup.js';
-import {doesHeatDataExist} from './SoftwareProductAttachmentsUtils.js';
+import { doesHeatDataExist } from './SoftwareProductAttachmentsUtils.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import SoftwareProductAttachmentsActionHelper from './SoftwareProductAttachmentsActionHelper.js';
 
-export const mapStateToProps = (state) => {
-       let {
-               softwareProduct: {
-                       softwareProductEditor:{data: currentSoftwareProduct = {}},
-                       softwareProductAttachments: {attachmentsDetails: {activeTab}, heatSetup, heatSetupCache, heatValidation : {errorList}}
-               }
-       } = state;
+export const mapStateToProps = state => {
+    let {
+        softwareProduct: {
+            softwareProductEditor: { data: currentSoftwareProduct = {} },
+            softwareProductAttachments: {
+                attachmentsDetails: { activeTab },
+                heatSetup,
+                heatSetupCache,
+                heatValidation: { errorList }
+            }
+        }
+    } = state;
 
-       let {unassigned = [], modules = []} = heatSetup;
-       let goToOverview = true;
-       if (errorList) {
-               for (let i = 0 ; i < errorList.length ; i++) {
-                       if (errorList[i].level === errorLevels.ERROR) {
-                               goToOverview = false;
-                       }
-               }
-       }
-       let heatDataExist = doesHeatDataExist(heatSetup);
+    let { unassigned = [], modules = [] } = heatSetup;
+    let goToOverview = true;
+    if (errorList) {
+        for (let i = 0; i < errorList.length; i++) {
+            if (errorList[i].level === errorLevels.ERROR) {
+                goToOverview = false;
+            }
+        }
+    }
+    let heatDataExist = doesHeatDataExist(heatSetup);
 
-       let {version, onboardingOrigin} = currentSoftwareProduct;
-       return {
-               isValidationAvailable: unassigned.length === 0 && modules.length > 0,
-               heatSetup,
-               heatSetupCache,
-               heatDataExist,
-               goToOverview,
-               HeatSetupComponent: HeatSetup,
-               version,
-               onboardingOrigin,
-               activeTab,
-               candidateInProcess: !!currentSoftwareProduct.candidateOnboardingOrigin
-       };
+    let { version, onboardingOrigin } = currentSoftwareProduct;
+    return {
+        isValidationAvailable: unassigned.length === 0 && modules.length > 0,
+        heatSetup,
+        heatSetupCache,
+        heatDataExist,
+        goToOverview,
+        HeatSetupComponent: HeatSetup,
+        version,
+        onboardingOrigin,
+        activeTab,
+        candidateInProcess: !!currentSoftwareProduct.candidateOnboardingOrigin
+    };
 };
 
-export const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onDownload: ({heatCandidate, isReadOnlyMode}) => SoftwareProductActionHelper.downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}),
-               onUpload: (formData) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Upload will erase existing data. Do you want to continue?'),
-                               confirmationButtonText: i18n('Continue'),
-                               title: i18n('WARNING'),
+export const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onDownload: ({ heatCandidate, isReadOnlyMode }) =>
+            SoftwareProductActionHelper.downloadHeatFile(dispatch, {
+                softwareProductId,
+                heatCandidate,
+                isReadOnlyMode,
+                version
+            }),
+        onUpload: formData =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n(
+                        'Upload will erase existing data. Do you want to continue?'
+                    ),
+                    confirmationButtonText: i18n('Continue'),
+                    title: i18n('WARNING'),
 
-                               onConfirmed: ()=>SoftwareProductActionHelper.uploadFile(dispatch, {
-                                       softwareProductId,
-                                       formData,
-                                       failedNotificationTitle: i18n('Upload validation failed'),
-                                       version
-                               })
-                       }
-               }),
-               onUploadAbort: () => {
-                       SoftwareProductActionHelper.abortCandidateValidation(dispatch, {softwareProductId, version})
-                               .then(()=>{
-                                       ScreensHelper.loadScreen(dispatch, {
-                                               screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                               props: {softwareProductId, version}
-                                       });
-                               });
-               },
-               onInvalidFileUpload: () => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                       data: {
-                               title: i18n('Upload Failed'),
-                               confirmationButtonText: i18n('Continue'),
-                               msg: i18n('no zip or csar file was uploaded or expected file doesn\'t exist')
-                       }
-               }),
-               onSave: (heatCandidate) => SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}),
-               onGoToOverview: () => ScreensHelper.loadScreen(dispatch, {
-                       screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                       props: {softwareProductId, version}
-               }),
-               onProcessAndValidate: ({heatData, heatDataCache, isReadOnlyMode}) => {
-                       return HeatSetupActionHelper.processAndValidateHeat(dispatch,
-                               {softwareProductId, heatData, heatDataCache, isReadOnlyMode, version});
-               },
-               setActiveTab: ({activeTab}) => SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {activeTab})
-
-       };
+                    onConfirmed: () =>
+                        SoftwareProductActionHelper.uploadFile(dispatch, {
+                            softwareProductId,
+                            formData,
+                            failedNotificationTitle: i18n(
+                                'Upload validation failed'
+                            ),
+                            version
+                        })
+                }
+            }),
+        onUploadAbort: () => {
+            SoftwareProductActionHelper.abortCandidateValidation(dispatch, {
+                softwareProductId,
+                version
+            }).then(() => {
+                ScreensHelper.loadScreen(dispatch, {
+                    screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                    screenType: screenTypes.SOFTWARE_PRODUCT,
+                    props: { softwareProductId, version }
+                });
+            });
+        },
+        onInvalidFileUpload: () =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                data: {
+                    title: i18n('Upload Failed'),
+                    confirmationButtonText: i18n('Continue'),
+                    msg: i18n(
+                        "no zip or csar file was uploaded or expected file doesn't exist"
+                    )
+                }
+            }),
+        onSave: heatCandidate =>
+            SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(
+                dispatch,
+                {
+                    softwareProductId,
+                    heatCandidate,
+                    version
+                }
+            ),
+        onGoToOverview: () =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: { softwareProductId, version }
+            }),
+        onProcessAndValidate: ({ heatData, heatDataCache, isReadOnlyMode }) => {
+            return HeatSetupActionHelper.processAndValidateHeat(dispatch, {
+                softwareProductId,
+                heatData,
+                heatDataCache,
+                isReadOnlyMode,
+                version
+            });
+        },
+        setActiveTab: ({ activeTab }) =>
+            SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {
+                activeTab
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductAttachmentsView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductAttachmentsView);
index ae4a615..2d35bc2 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes} from './SoftwareProductAttachmentsConstants';
+import { actionTypes } from './SoftwareProductAttachmentsConstants';
 
 export default {
-       setActiveTab(dispatch, {activeTab}) {
-               dispatch({
-                       type: actionTypes.SET_ACTIVE_TAB,
-                       activeTab
-               });
-       }
+    setActiveTab(dispatch, { activeTab }) {
+        dispatch({
+            type: actionTypes.SET_ACTIVE_TAB,
+            activeTab
+        });
+    }
 };
index 6726590..aff0a3d 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const tabsMapping = {
-       SETUP: 1,
-       VALIDATION: 2
+    SETUP: 1,
+    VALIDATION: 2
 };
 
 export const actionTypes = keyMirror({
-       SET_ACTIVE_TAB: null
+    SET_ACTIVE_TAB: null
 });
index 5f6538a..5d9a37f 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductAttachmentsConstants.js';
+import { actionTypes } from './SoftwareProductAttachmentsConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.SET_ACTIVE_TAB:
-                       return {activeTab: action.activeTab};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.SET_ACTIVE_TAB:
+            return { activeTab: action.activeTab };
+        default:
+            return state;
+    }
 };
index 2e76b11..f4e7722 100644 (file)
  */
 
 export function doesHeatDataExist(heatData) {
-       let result = false;
-       for (let key of Object.keys(heatData)) {
-               if(heatData[key].length > 0) {
-                       result = true;
-               }
-       }
-       return result;
+    let result = false;
+    for (let key of Object.keys(heatData)) {
+        if (heatData[key].length > 0) {
+            result = true;
+        }
+    }
+    return result;
 }
index 2a849f3..2007493 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import accept from 'attr-accept';
-import {SVGIcon, Tab, Tabs} from 'sdc-ui/lib/react';
-import {tabsMapping} from './SoftwareProductAttachmentsConstants.js';
+import { SVGIcon, Tab, Tabs } from 'sdc-ui/lib/react';
+import { tabsMapping } from './SoftwareProductAttachmentsConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import HeatValidation from './validation/HeatValidation.js';
-import {onboardingOriginTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { onboardingOriginTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 import Button from 'sdc-ui/lib/react/Button.js';
 
 class HeatScreenView extends Component {
+    static propTypes = {
+        isValidationAvailable: PropTypes.bool,
+        goToOverview: PropTypes.bool,
+        setActiveTab: PropTypes.func
+    };
 
-       static propTypes = {
-               isValidationAvailable: PropTypes.bool,
-               goToOverview: PropTypes.bool,
-               setActiveTab: PropTypes.func
-       };
+    componentDidMount() {
+        if (!this.props.goToOverview && this.props.candidateInProcess) {
+            this.props.setActiveTab({ activeTab: tabsMapping.VALIDATION });
+        }
+    }
 
-       componentDidMount() {
-                if (!this.props.goToOverview && this.props.candidateInProcess) {
-                       this.props.setActiveTab({activeTab: tabsMapping.VALIDATION});
-                }
-       }
+    render() {
+        let {
+            isValidationAvailable,
+            isReadOnlyMode,
+            heatDataExist,
+            onDownload,
+            softwareProductId,
+            onProcessAndValidate,
+            onUploadAbort,
+            candidateInProcess,
+            heatSetup,
+            HeatSetupComponent,
+            onGoToOverview,
+            version,
+            onboardingOrigin,
+            activeTab,
+            setActiveTab,
+            ...other
+        } = this.props;
 
-       render() {
-               let {isValidationAvailable, isReadOnlyMode, heatDataExist, onDownload, softwareProductId, onProcessAndValidate, onUploadAbort,
-                       candidateInProcess, heatSetup, HeatSetupComponent, onGoToOverview, version, onboardingOrigin, activeTab, setActiveTab, ...other} = this.props;
+        return (
+            <div className="vsp-attachments-view">
+                <div className="attachments-view-controllers">
+                    {activeTab === tabsMapping.SETUP &&
+                        candidateInProcess && (
+                            <Button
+                                data-test-id="proceed-to-validation-btn"
+                                disabled={!isValidationAvailable}
+                                className="proceed-to-validation-btn"
+                                onClick={() => this.validate()}>
+                                {i18n('PROCEED TO VALIDATION')}
+                            </Button>
+                        )}
+                    {candidateInProcess && (
+                        <SVGIcon
+                            onClick={onUploadAbort}
+                            name="close"
+                            className="icon-component abort-btn"
+                            label={i18n('ABORT')}
+                            labelPosition="right"
+                            color="secondary"
+                            data-test-id="abort-btn"
+                        />
+                    )}
+                    {activeTab === tabsMapping.VALIDATION &&
+                        softwareProductId && (
+                            <Button
+                                btnType="outline"
+                                data-test-id="go-to-overview"
+                                disabled={this.props.goToOverview !== true}
+                                className="go-to-overview-btn"
+                                onClick={
+                                    this.props.goToOverview
+                                        ? () => onGoToOverview({ version })
+                                        : undefined
+                                }>
+                                {i18n('GO TO OVERVIEW')}
+                            </Button>
+                        )}
+                    <div className="separator" />
+                    <SVGIcon
+                        disabled={heatDataExist ? false : true}
+                        name="download"
+                        className="icon-component"
+                        color="dark-gray"
+                        onClick={
+                            heatDataExist
+                                ? () =>
+                                      onDownload({
+                                          heatCandidate: heatSetup,
+                                          isReadOnlyMode:
+                                              isReadOnlyMode ||
+                                              !candidateInProcess,
+                                          version
+                                      })
+                                : undefined
+                        }
+                        data-test-id="download-heat"
+                    />
+                    <SVGIcon
+                        name="upload"
+                        className="icon-component"
+                        color="dark-gray"
+                        disabled={isReadOnlyMode || candidateInProcess}
+                        onClick={
+                            isReadOnlyMode
+                                ? undefined
+                                : evt =>
+                                      this.refs.hiddenImportFileInput.click(evt)
+                        }
+                        data-test-id="upload-heat"
+                    />
+                    <input
+                        ref="hiddenImportFileInput"
+                        type="file"
+                        name="fileInput"
+                        accept=".zip, .csar"
+                        onChange={evt => this.handleImport(evt)}
+                    />
+                </div>
+                <Tabs
+                    className="attachments-tabs"
+                    type="header"
+                    activeTab={activeTab}
+                    onTabClick={key => this.handleTabPress(key)}>
+                    <Tab
+                        tabId={tabsMapping.SETUP}
+                        title="Setup"
+                        disabled={
+                            onboardingOrigin === onboardingOriginTypes.CSAR
+                        }>
+                        <HeatSetupComponent
+                            heatDataExist={heatDataExist}
+                            changeAttachmentsTab={tab =>
+                                setActiveTab({ activeTab: tab })
+                            }
+                            onProcessAndValidate={onProcessAndValidate}
+                            softwareProductId={softwareProductId}
+                            isReadOnlyMode={isReadOnlyMode}
+                            version={version}
+                        />
+                    </Tab>
+                    <Tab
+                        tabId={tabsMapping.VALIDATION}
+                        title="Validation"
+                        disabled={!isValidationAvailable || candidateInProcess}>
+                        <HeatValidation {...other} />
+                    </Tab>
+                </Tabs>
+            </div>
+        );
+    }
 
-               return (
-                       <div className='vsp-attachments-view'>
-                               <div className='attachments-view-controllers'>
-                                       {(activeTab === tabsMapping.SETUP) && candidateInProcess &&     
-                                               <Button  
-                                                       data-test-id='proceed-to-validation-btn'
-                                                       disabled={!isValidationAvailable} 
-                                                       className='proceed-to-validation-btn'
-                                                       onClick={()=>this.validate()}>{i18n('PROCEED TO VALIDATION')}</Button>
-                                       }
-                                       {candidateInProcess && <SVGIcon
-                                               onClick={onUploadAbort}
-                                               name='close'
-                                               className='icon-component abort-btn'
-                                               label={i18n('ABORT')}
-                                               labelPosition='right'
-                                               color='secondary'
-                                               data-test-id='abort-btn'/>
-                                       }
-                                       {(activeTab === tabsMapping.VALIDATION && softwareProductId) &&
-                                               <Button btnType='outline' 
-                                                       data-test-id='go-to-overview'
-                                                       disabled={this.props.goToOverview !== true}
-                                                       className='go-to-overview-btn'
-                                                       onClick={this.props.goToOverview ? () => onGoToOverview({version}) : undefined}>{i18n('GO TO OVERVIEW')}</Button>}                                              
-                                       <div className='separator'></div>
-                                       <SVGIcon
-                                               disabled={heatDataExist ? false : true}
-                                               name='download'
-                                               className='icon-component'
-                                               color='dark-gray'
-                                               onClick={heatDataExist ? () => onDownload({heatCandidate: heatSetup, isReadOnlyMode: isReadOnlyMode || !candidateInProcess, version}) : undefined}
-                                               data-test-id='download-heat'/>
-                                       <SVGIcon
-                                               name='upload'
-                                               className='icon-component'
-                                               color='dark-gray'
-                                               disabled={isReadOnlyMode || candidateInProcess}
-                                               onClick={isReadOnlyMode ? undefined : evt => this.refs.hiddenImportFileInput.click(evt)}
-                                               data-test-id='upload-heat'/>
-                                       <input
-                                               ref='hiddenImportFileInput'
-                                               type='file'
-                                               name='fileInput'
-                                               accept='.zip, .csar'
-                                               onChange={evt => this.handleImport(evt)}/>
-                               </div>
-                               <Tabs
-                                       className='attachments-tabs'
-                                       type='header'
-                                       activeTab={activeTab}
-                                       onTabClick={key => this.handleTabPress(key)}>
-                                       <Tab tabId={tabsMapping.SETUP} title='Setup' disabled={onboardingOrigin === onboardingOriginTypes.CSAR}>
-                                               <HeatSetupComponent
-                                                       heatDataExist={heatDataExist}
-                                                       changeAttachmentsTab={tab => setActiveTab({activeTab: tab})}
-                                                       onProcessAndValidate={onProcessAndValidate}
-                                                       softwareProductId={softwareProductId}
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       version={version}/>
-                                       </Tab>
-                                       <Tab tabId={tabsMapping.VALIDATION} title='Validation' disabled={!isValidationAvailable || candidateInProcess}>
-                                               <HeatValidation {...other}/>
-                                       </Tab>
-                               </Tabs>
-                       </div>
-               );
-       }
-
-       handleTabPress(key) {
-               let {setActiveTab} = this.props;
-               switch (key) {
-                       case tabsMapping.VALIDATION:
-                               setActiveTab({activeTab: tabsMapping.VALIDATION});              
-                               return;
-                       case tabsMapping.SETUP:
-                               setActiveTab({activeTab: tabsMapping.SETUP});
-                               return;
-               }
-       }
-
-       handleImport(evt) {
-               evt.preventDefault();
-               let file = this.refs.hiddenImportFileInput.files[0];
-               if(! (file && file.size && accept(file, ['.zip', '.csar'])) ) {
-                       this.props.onInvalidFileUpload();
-                       return;
-               }
-               let {version} = this.props;
-               let formData = new FormData();
-               formData.append('upload', file);
-               this.refs.hiddenImportFileInput.value = '';
-               this.props.onUpload(formData, version);
-       }
-       validate() {
-               let {heatSetup, heatSetupCache, onProcessAndValidate, isReadOnlyMode, version, setActiveTab} = this.props;
-               onProcessAndValidate({heatData: heatSetup, heatDataCache: heatSetupCache, isReadOnlyMode, version}).then(
-                       () => setActiveTab({activeTab: tabsMapping.VALIDATION})
-               );
-       }
-       save() {
-               return this.props.onboardingOrigin === onboardingOriginTypes.ZIP ?
-                       this.props.onSave(this.props.heatSetup, this.props.version) :
-                       Promise.resolve();
-       }
+    handleTabPress(key) {
+        let { setActiveTab } = this.props;
+        switch (key) {
+            case tabsMapping.VALIDATION:
+                setActiveTab({ activeTab: tabsMapping.VALIDATION });
+                return;
+            case tabsMapping.SETUP:
+                setActiveTab({ activeTab: tabsMapping.SETUP });
+                return;
+        }
+    }
 
+    handleImport(evt) {
+        evt.preventDefault();
+        let file = this.refs.hiddenImportFileInput.files[0];
+        if (!(file && file.size && accept(file, ['.zip', '.csar']))) {
+            this.props.onInvalidFileUpload();
+            return;
+        }
+        let { version } = this.props;
+        let formData = new FormData();
+        formData.append('upload', file);
+        this.refs.hiddenImportFileInput.value = '';
+        this.props.onUpload(formData, version);
+    }
+    validate() {
+        let {
+            heatSetup,
+            heatSetupCache,
+            onProcessAndValidate,
+            isReadOnlyMode,
+            version,
+            setActiveTab
+        } = this.props;
+        onProcessAndValidate({
+            heatData: heatSetup,
+            heatDataCache: heatSetupCache,
+            isReadOnlyMode,
+            version
+        }).then(() => setActiveTab({ activeTab: tabsMapping.VALIDATION }));
+    }
+    save() {
+        return this.props.onboardingOrigin === onboardingOriginTypes.ZIP
+            ? this.props.onSave(this.props.heatSetup, this.props.version)
+            : Promise.resolve();
+    }
 }
 
 export default HeatScreenView;
index 4c3adc6..d75d464 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import HeatSetupView from './HeatSetupView.jsx';
 import HeatSetupActionHelper from './HeatSetupActionHelper.js';
 
-
 const BASE = true;
 
 function baseExists(modules) {
-       for (let i in modules) {
-               if (modules[i].isBase) {
-                       return true;
-               }
-       }
-       return false;
+    for (let i in modules) {
+        if (modules[i].isBase) {
+            return true;
+        }
+    }
+    return false;
 }
 
-export const mapStateToProps = ({softwareProduct: {softwareProductAttachments: {heatSetup, heatSetupCache}}}) => {
-       let {modules = [], unassigned = [], artifacts = [], nested = []} = heatSetup;
-       let isBaseExist = baseExists(modules);
+export const mapStateToProps = ({
+    softwareProduct: {
+        softwareProductAttachments: { heatSetup, heatSetupCache }
+    }
+}) => {
+    let {
+        modules = [],
+        unassigned = [],
+        artifacts = [],
+        nested = []
+    } = heatSetup;
+    let isBaseExist = baseExists(modules);
 
-       return {
-               heatSetupCache,
-               modules,
-               unassigned,
-               artifacts,
-               nested,
-               isBaseExist
-       };
+    return {
+        heatSetupCache,
+        modules,
+        unassigned,
+        artifacts,
+        nested,
+        isBaseExist
+    };
 };
 
 export const mapActionsToProps = (dispatch, {}) => {
-       return {
-               onModuleRename: (oldName, newName) => HeatSetupActionHelper.renameModule(dispatch, {oldName, newName}),
-               onModuleAdd: () => HeatSetupActionHelper.addModule(dispatch, !BASE),
-               onBaseAdd: () => HeatSetupActionHelper.addModule(dispatch, BASE),
-               onModuleDelete: moduleName => HeatSetupActionHelper.deleteModule(dispatch, moduleName),
-               onModuleFileTypeChange: ({module, value, type}) => HeatSetupActionHelper.changeModuleFileType(dispatch, {
-                       module,
-                       value,
-                       type
-               }),
-               onArtifactListChange: artifacts => HeatSetupActionHelper.changeArtifactList(dispatch, artifacts),
-               onAddAllUnassigned: () => HeatSetupActionHelper.addAllUnassignedFilesToArtifacts(dispatch)
-       };
+    return {
+        onModuleRename: (oldName, newName) =>
+            HeatSetupActionHelper.renameModule(dispatch, { oldName, newName }),
+        onModuleAdd: () => HeatSetupActionHelper.addModule(dispatch, !BASE),
+        onBaseAdd: () => HeatSetupActionHelper.addModule(dispatch, BASE),
+        onModuleDelete: moduleName =>
+            HeatSetupActionHelper.deleteModule(dispatch, moduleName),
+        onModuleFileTypeChange: ({ module, value, type }) =>
+            HeatSetupActionHelper.changeModuleFileType(dispatch, {
+                module,
+                value,
+                type
+            }),
+        onArtifactListChange: artifacts =>
+            HeatSetupActionHelper.changeArtifactList(dispatch, artifacts),
+        onAddAllUnassigned: () =>
+            HeatSetupActionHelper.addAllUnassignedFilesToArtifacts(dispatch)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(HeatSetupView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(HeatSetupView);
index 87953bb..05ac408 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './HeatSetupConstants.js';
+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';
@@ -21,46 +21,72 @@ import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/Soft
 // import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
 
 export default {
+    addModule(dispatch, isBase) {
+        dispatch({ type: actionTypes.ADD_MODULE, data: { isBase } });
+    },
 
-       addModule(dispatch, isBase){
-               dispatch({type: actionTypes.ADD_MODULE, data: {isBase}});
-       },
+    deleteModule(dispatch, moduleName) {
+        dispatch({ type: actionTypes.REMOVE_MODULE, data: { moduleName } });
+    },
 
-       deleteModule(dispatch, moduleName){
-               dispatch({type: actionTypes.REMOVE_MODULE, data: {moduleName}});
-       },
+    renameModule(dispatch, { oldName, newName }) {
+        dispatch({
+            type: actionTypes.RENAME_MODULE,
+            data: { oldName, newName }
+        });
+    },
 
-       renameModule(dispatch, {oldName, newName}){
-               dispatch({type: actionTypes.RENAME_MODULE, data: {oldName, newName}});
-       },
+    changeModuleFileType(dispatch, { module, value, type }) {
+        if (!value) {
+            value = { value: '' };
+        }
+        dispatch({
+            type: actionTypes.FILE_ASSIGN_CHANGED,
+            data: { module, value, type }
+        });
+    },
 
-       changeModuleFileType(dispatch, {module, value, type}){
-               if (!value) {
-                       value = {value: ''};
-               }
-               dispatch({type: actionTypes.FILE_ASSIGN_CHANGED, data: {module, value, type}});
-       },
+    changeArtifactList(dispatch, artifacts) {
+        dispatch({
+            type: actionTypes.ARTIFACT_LIST_CHANGE,
+            data: { artifacts: artifacts.map(artifact => artifact.value) }
+        });
+    },
 
-       changeArtifactList(dispatch, artifacts){
-               dispatch({type: actionTypes.ARTIFACT_LIST_CHANGE, data: {artifacts: artifacts.map(artifact => artifact.value)}});
-       },
+    processAndValidateHeat(
+        dispatch,
+        { softwareProductId, heatData, heatDataCache, isReadOnlyMode, version }
+    ) {
+        return isEqual({ ...heatData, softwareProductId }, heatDataCache) ||
+            isReadOnlyMode
+            ? Promise.resolve()
+            : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(
+                  dispatch,
+                  { softwareProductId, heatCandidate: heatData, version }
+              )
+                  .then(() =>
+                      SoftwareProductActionHelper.processAndValidateHeatCandidate(
+                          dispatch,
+                          { softwareProductId, version }
+                      )
+                  )
+                  .then(() =>
+                      dispatch({
+                          type: actionTypes.FILL_HEAT_SETUP_CACHE,
+                          payload: { ...cloneDeep(heatData), softwareProductId }
+                      })
+                  );
+    },
 
-       processAndValidateHeat(dispatch, {softwareProductId, heatData, heatDataCache, isReadOnlyMode, version}){                
-               return (isEqual({...heatData, softwareProductId}, heatDataCache) || isReadOnlyMode) ? Promise.resolve() :
-               SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate: heatData, version})
-                       .then(() => SoftwareProductActionHelper.processAndValidateHeatCandidate(dispatch, {softwareProductId, version}))
-                       .then(() => dispatch({type: actionTypes.FILL_HEAT_SETUP_CACHE, payload: {...cloneDeep(heatData), softwareProductId}}));
-       },
+    addAllUnassignedFilesToArtifacts(dispatch) {
+        dispatch({ type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS });
+    },
 
-       addAllUnassignedFilesToArtifacts(dispatch){
-               dispatch({type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS});
-       },
+    heatSetupLeaveConfirmation() {
+        return Promise.resolve();
+    }
 
-       heatSetupLeaveConfirmation() {
-               return Promise.resolve();
-       }
-
-       /*heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) {
+    /*heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) {
                return new Promise((resolve, reject) => {
                        if (isEqual({...heatSetup, softwareProductId}, heatSetupCache)) {
                                resolve();
index 2d6bd57..ff53fad 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
+    ARTIFACT_LIST_CHANGE: null,
+    ADD_ALL_UNASSIGNED_TO_ARTIFACTS: null,
+    ADD_ALL_ARTIFACTS_TO_UNASSIGNED: null,
 
-       ARTIFACT_LIST_CHANGE: null,
-       ADD_ALL_UNASSIGNED_TO_ARTIFACTS: null,
-       ADD_ALL_ARTIFACTS_TO_UNASSIGNED: null,
+    ADD_MODULE: null,
+    REMOVE_MODULE: null,
+    RENAME_MODULE: null,
+    FILL_HEAT_SETUP_CACHE: null,
+    FILE_ASSIGN_CHANGED: null,
 
-       ADD_MODULE: null,
-       REMOVE_MODULE: null,
-       RENAME_MODULE: null,
-       FILL_HEAT_SETUP_CACHE: null,
-       FILE_ASSIGN_CHANGED: null,
-
-       MANIFEST_LOADED: null,
-
-       GO_TO_VALIDATION: null,
-       IN_VALIDATION: null
+    MANIFEST_LOADED: null,
 
+    GO_TO_VALIDATION: null,
+    IN_VALIDATION: null
 });
 
 export const fileTypes = {
-       YAML: {label: 'yaml', regex: /(yaml|yml)/g},
-       ENV: {label: 'env', regex: /env/g},
-       VOL: {label: 'vol', regex: /(yaml|yml)/g},
-       VOL_ENV: {label: 'volEnv', regex: /env/g}
+    YAML: { label: 'yaml', regex: /(yaml|yml)/g },
+    ENV: { label: 'env', regex: /env/g },
+    VOL: { label: 'vol', regex: /(yaml|yml)/g },
+    VOL_ENV: { label: 'volEnv', regex: /env/g }
 };
index f49339c..8840a11 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './HeatSetupConstants.js';
+import { actionTypes } from './HeatSetupConstants.js';
 import differenceWith from 'lodash/differenceWith.js';
 
-
 const emptyModule = (isBase, currentLength) => ({
-       name: `${isBase ? 'base_' : 'module_'}${currentLength + 1}`,
-       isBase: isBase
+    name: `${isBase ? 'base_' : 'module_'}${currentLength + 1}`,
+    isBase: isBase
 });
 
-function syncUnassignedFilesWithArtifactsChanges(unassigned, artifacts, oldArtifacts) {
-       if (artifacts.length > oldArtifacts.length) {
-               return differenceWith(unassigned, artifacts, (unassignedFile, artifact) => unassignedFile === artifact);
-       }
-       else {
-               const removedArtifact = differenceWith(oldArtifacts, artifacts, (oldArtifact, artifact) => artifact === oldArtifact);
-               return [...unassigned, removedArtifact[0]];
-       }
+function syncUnassignedFilesWithArtifactsChanges(
+    unassigned,
+    artifacts,
+    oldArtifacts
+) {
+    if (artifacts.length > oldArtifacts.length) {
+        return differenceWith(
+            unassigned,
+            artifacts,
+            (unassignedFile, artifact) => unassignedFile === artifact
+        );
+    } else {
+        const removedArtifact = differenceWith(
+            oldArtifacts,
+            artifacts,
+            (oldArtifact, artifact) => artifact === oldArtifact
+        );
+        return [...unassigned, removedArtifact[0]];
+    }
 }
 
 function findModuleIndexByName(modules, name) {
-       return modules.findIndex(module => module.name === name);
+    return modules.findIndex(module => module.name === name);
 }
 
-function addDeletedModuleFilesToUnassigned(unassigned, deletedModule){
-       let files = [];
-       for(let i in deletedModule){
-               if (deletedModule.hasOwnProperty(i)) {
-                       if (typeof deletedModule[i] === 'string' && deletedModule[i] && i !== 'name') {
-                               files.push(deletedModule[i]);
-                       }
-               }
-       }
+function addDeletedModuleFilesToUnassigned(unassigned, deletedModule) {
+    let files = [];
+    for (let i in deletedModule) {
+        if (deletedModule.hasOwnProperty(i)) {
+            if (
+                typeof deletedModule[i] === 'string' &&
+                deletedModule[i] &&
+                i !== 'name'
+            ) {
+                files.push(deletedModule[i]);
+            }
+        }
+    }
 
-       return unassigned.concat(files);
+    return unassigned.concat(files);
 }
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.MANIFEST_LOADED:
-                       return {
-                               ...state,
-                               ...action.response,
-                               modules: action.response.modules.map(module => ({...module, name: module.name || module.yaml.substring(0, module.yaml.lastIndexOf('.'))}))
-                       };
-               case actionTypes.ARTIFACT_LIST_CHANGE:
-                       return {
-                               ...state,
-                               artifacts: action.data.artifacts,
-                               unassigned: syncUnassignedFilesWithArtifactsChanges(state.unassigned, action.data.artifacts, state.artifacts)
-                       };
-               case actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS:
-                       return {
-                               ...state,
-                               artifacts: [...state.artifacts,...state.unassigned],
-                               unassigned: []
-                       };
-               case actionTypes.ADD_ALL_ARTIFACTS_TO_UNASSIGNED:
-                       return {
-                               ...state,
-                               artifacts: [],
-                               unassigned: [...state.unassigned, ...state.artifacts]
-                       };
-               case actionTypes.ADD_MODULE:
-                       return {
-                               ...state,
-                               modules: state.modules.concat({...emptyModule(action.data.isBase, state.modules.length)})
-                       };
-               case actionTypes.REMOVE_MODULE:
-                       const moduleIndexToDelete = findModuleIndexByName(state.modules, action.data.moduleName);
-                       let unassigned = addDeletedModuleFilesToUnassigned(state.unassigned, state.modules[moduleIndexToDelete]);
-                       return {
-                               ...state,
-                               unassigned,
-                               modules: [...state.modules.slice(0, moduleIndexToDelete), ...state.modules.slice(moduleIndexToDelete + 1)]
-                       };
-               case actionTypes.RENAME_MODULE:
-                       const indexToRename = findModuleIndexByName(state.modules, action.data.oldName);
-                       let moduleToRename = state.modules[indexToRename];
-                       moduleToRename.name = action.data.newName;
-                       return {
-                               ...state,
-                               modules: [...state.modules.slice(0, indexToRename), moduleToRename, ...state.modules.slice(indexToRename + 1)]
-                       };
-               case actionTypes.FILE_ASSIGN_CHANGED:
-                       let {module, value:{value}, type} = action.data;
-                       const moduleIndexToModify = findModuleIndexByName(state.modules, module.name);
-                       let moduleToModify = state.modules[moduleIndexToModify];
-                       let dumpedFile = moduleToModify[type];
-                       if (dumpedFile !== value) {
-                               if(value) {
-                                       moduleToModify[type] = value;
-                               }
-                               else {
-                                       delete moduleToModify[type];
-                               }
-                               const newUnassignedList = dumpedFile ? [...state.unassigned.filter(file => file !== value), dumpedFile] : state.unassigned.filter(file => file !== value);
-                               return {
-                                       ...state,
-                                       modules: [...state.modules.slice(0, moduleIndexToModify), moduleToModify, ...state.modules.slice(moduleIndexToModify + 1)],
-                                       unassigned: newUnassignedList
-                               };
-                       }
-                       else {
-                               return state;
-                       }
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.MANIFEST_LOADED:
+            return {
+                ...state,
+                ...action.response,
+                modules: action.response.modules.map(module => ({
+                    ...module,
+                    name:
+                        module.name ||
+                        module.yaml.substring(0, module.yaml.lastIndexOf('.'))
+                }))
+            };
+        case actionTypes.ARTIFACT_LIST_CHANGE:
+            return {
+                ...state,
+                artifacts: action.data.artifacts,
+                unassigned: syncUnassignedFilesWithArtifactsChanges(
+                    state.unassigned,
+                    action.data.artifacts,
+                    state.artifacts
+                )
+            };
+        case actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS:
+            return {
+                ...state,
+                artifacts: [...state.artifacts, ...state.unassigned],
+                unassigned: []
+            };
+        case actionTypes.ADD_ALL_ARTIFACTS_TO_UNASSIGNED:
+            return {
+                ...state,
+                artifacts: [],
+                unassigned: [...state.unassigned, ...state.artifacts]
+            };
+        case actionTypes.ADD_MODULE:
+            return {
+                ...state,
+                modules: state.modules.concat({
+                    ...emptyModule(action.data.isBase, state.modules.length)
+                })
+            };
+        case actionTypes.REMOVE_MODULE:
+            const moduleIndexToDelete = findModuleIndexByName(
+                state.modules,
+                action.data.moduleName
+            );
+            let unassigned = addDeletedModuleFilesToUnassigned(
+                state.unassigned,
+                state.modules[moduleIndexToDelete]
+            );
+            return {
+                ...state,
+                unassigned,
+                modules: [
+                    ...state.modules.slice(0, moduleIndexToDelete),
+                    ...state.modules.slice(moduleIndexToDelete + 1)
+                ]
+            };
+        case actionTypes.RENAME_MODULE:
+            const indexToRename = findModuleIndexByName(
+                state.modules,
+                action.data.oldName
+            );
+            let moduleToRename = state.modules[indexToRename];
+            moduleToRename.name = action.data.newName;
+            return {
+                ...state,
+                modules: [
+                    ...state.modules.slice(0, indexToRename),
+                    moduleToRename,
+                    ...state.modules.slice(indexToRename + 1)
+                ]
+            };
+        case actionTypes.FILE_ASSIGN_CHANGED:
+            let { module, value: { value }, type } = action.data;
+            const moduleIndexToModify = findModuleIndexByName(
+                state.modules,
+                module.name
+            );
+            let moduleToModify = state.modules[moduleIndexToModify];
+            let dumpedFile = moduleToModify[type];
+            if (dumpedFile !== value) {
+                if (value) {
+                    moduleToModify[type] = value;
+                } else {
+                    delete moduleToModify[type];
+                }
+                const newUnassignedList = dumpedFile
+                    ? [
+                          ...state.unassigned.filter(file => file !== value),
+                          dumpedFile
+                      ]
+                    : state.unassigned.filter(file => file !== value);
+                return {
+                    ...state,
+                    modules: [
+                        ...state.modules.slice(0, moduleIndexToModify),
+                        moduleToModify,
+                        ...state.modules.slice(moduleIndexToModify + 1)
+                    ],
+                    unassigned: newUnassignedList
+                };
+            } else {
+                return state;
+            }
+        default:
+            return state;
+    }
 };
index ce6d526..1d4efd9 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+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';
@@ -21,307 +21,476 @@ 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';
+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>
-               );
-       }
+    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>
-               );
-       }
+    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 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>
-       );
+    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 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 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} />
-       );
+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}/>
-               );
-       }
+    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>
-               );
-       }
+    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>
-               );
-       }
+    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>
+        );
+    }
 }
 
-const buildLabelValueObject = str => (typeof str === 'string' ? {value: str, label: str} : str);
+const buildLabelValueObject = str =>
+    typeof str === 'string' ? { value: str, label: str } : str;
 
 class SoftwareProductHeatSetupView extends Component {
-
-       processAndValidateHeat(heatData, heatDataCache){
-               let {onProcessAndValidate, changeAttachmentsTab, version} = this.props;
-               onProcessAndValidate({heatData, heatDataCache, version}).then(
-                       () => changeAttachmentsTab(tabsMapping.VALIDATION)
-               );
-       }
-
-       render() {
-               let {modules, isReadOnlyMode, heatDataExist, unassigned, artifacts, nested, onArtifactListChange, onAddAllUnassigned} = this.props;
-
-               const formattedUnassigned = unassigned.map(buildLabelValueObject);
-               const formattedArtifacts = artifacts.map(buildLabelValueObject);
-               return (
-                       <div className={`heat-setup-view ${isReadOnlyMode ? 'disabled' : ''}`}>
-                               <div className='heat-setup-view-modules-and-artifacts'>
-                                       <SortableModuleFileList
-                                               {...this.props}
-                                               isReadOnlyMode={this.props.isReadOnlyMode}
-                                               artifacts={formattedArtifacts}
-                                               unassigned={formattedUnassigned}/>
-                                       <ArtifactOrNestedFileList
-                                               type={'artifact'}
-                                               title={i18n('ARTIFACTS')}
-                                               options={formattedUnassigned}
-                                               selected={formattedArtifacts}
-                                               onSelectChanged={onArtifactListChange}
-                                               isReadOnlyMode={this.props.isReadOnlyMode}
-                                               headerClassName={(modules && modules.length > 0) ? 'with-list-items' : ''}
-                                               onAddAllUnassigned={onAddAllUnassigned}/>
-                                       <ArtifactOrNestedFileList
-                                               type={'nested'}
-                                               title={i18n('NESTED HEAT FILES')}
-                                               options={[]}
-                                               isReadOnlyMode={this.props.isReadOnlyMode}
-                                               selected={nested}/>
-                               </div>
-                               <UnassignedFileList>
-                                       {
-                                               formattedUnassigned.length > 0 ?
-                                               (<ul>{formattedUnassigned.map(file => <UnassignedFile key={file.label} name={file.label}/>)}</ul>)
-                                               :
-                                               (<EmptyListContent
-                                                       heatDataExist={heatDataExist}/>)
-                                       }
-                               </UnassignedFileList>
-                       </div>
-               );
-       }
-
+    processAndValidateHeat(heatData, heatDataCache) {
+        let {
+            onProcessAndValidate,
+            changeAttachmentsTab,
+            version
+        } = this.props;
+        onProcessAndValidate({ heatData, heatDataCache, version }).then(() =>
+            changeAttachmentsTab(tabsMapping.VALIDATION)
+        );
+    }
+
+    render() {
+        let {
+            modules,
+            isReadOnlyMode,
+            heatDataExist,
+            unassigned,
+            artifacts,
+            nested,
+            onArtifactListChange,
+            onAddAllUnassigned
+        } = this.props;
+
+        const formattedUnassigned = unassigned.map(buildLabelValueObject);
+        const formattedArtifacts = artifacts.map(buildLabelValueObject);
+        return (
+            <div
+                className={`heat-setup-view ${
+                    isReadOnlyMode ? 'disabled' : ''
+                }`}>
+                <div className="heat-setup-view-modules-and-artifacts">
+                    <SortableModuleFileList
+                        {...this.props}
+                        isReadOnlyMode={this.props.isReadOnlyMode}
+                        artifacts={formattedArtifacts}
+                        unassigned={formattedUnassigned}
+                    />
+                    <ArtifactOrNestedFileList
+                        type={'artifact'}
+                        title={i18n('ARTIFACTS')}
+                        options={formattedUnassigned}
+                        selected={formattedArtifacts}
+                        onSelectChanged={onArtifactListChange}
+                        isReadOnlyMode={this.props.isReadOnlyMode}
+                        headerClassName={
+                            modules && modules.length > 0
+                                ? 'with-list-items'
+                                : ''
+                        }
+                        onAddAllUnassigned={onAddAllUnassigned}
+                    />
+                    <ArtifactOrNestedFileList
+                        type={'nested'}
+                        title={i18n('NESTED HEAT FILES')}
+                        options={[]}
+                        isReadOnlyMode={this.props.isReadOnlyMode}
+                        selected={nested}
+                    />
+                </div>
+                <UnassignedFileList>
+                    {formattedUnassigned.length > 0 ? (
+                        <ul>
+                            {formattedUnassigned.map(file => (
+                                <UnassignedFile
+                                    key={file.label}
+                                    name={file.label}
+                                />
+                            ))}
+                        </ul>
+                    ) : (
+                        <EmptyListContent heatDataExist={heatDataExist} />
+                    )}
+                </UnassignedFileList>
+            </div>
+        );
+    }
 }
 
 export default SoftwareProductHeatSetupView;
index 21f6e6c..00130e4 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import HeatValidationView from './HeatValidationView.jsx';
 import HeatValidationActionHelper from './HeatValidationActionHelper.js';
-import {errorLevels, nodeFilters} from './HeatValidationConstants.js';
+import { errorLevels, nodeFilters } from './HeatValidationConstants.js';
 
-export const mapStateToProps = ({softwareProduct: {softwareProductAttachments: {heatValidation}}}) => {
-       let {attachmentsTree, selectedNode, errorList} = heatValidation;
-       let currentErrors = [], currentWarnings = [];
-       if (errorList) {
-               for (let i = 0 ; i < errorList.length ; i++) {
-                       if (errorList[i].level === errorLevels.ERROR && (errorList[i].name === selectedNode || selectedNode === nodeFilters.ALL)) {
-                               currentErrors[currentErrors.length] = errorList[i];
-                       }
-                       if (errorList[i].level === errorLevels.WARNING  && (errorList[i].name === selectedNode || selectedNode === nodeFilters.ALL)) {
-                               currentWarnings[currentWarnings.length] = errorList[i];
-                       }
-               }
-       }
-       return {
-               attachmentsTree,
-               selectedNode,
-               errorList,
-               currentErrors,
-               currentWarnings
-       };
+export const mapStateToProps = ({
+    softwareProduct: { softwareProductAttachments: { heatValidation } }
+}) => {
+    let { attachmentsTree, selectedNode, errorList } = heatValidation;
+    let currentErrors = [],
+        currentWarnings = [];
+    if (errorList) {
+        for (let i = 0; i < errorList.length; i++) {
+            if (
+                errorList[i].level === errorLevels.ERROR &&
+                (errorList[i].name === selectedNode ||
+                    selectedNode === nodeFilters.ALL)
+            ) {
+                currentErrors[currentErrors.length] = errorList[i];
+            }
+            if (
+                errorList[i].level === errorLevels.WARNING &&
+                (errorList[i].name === selectedNode ||
+                    selectedNode === nodeFilters.ALL)
+            ) {
+                currentWarnings[currentWarnings.length] = errorList[i];
+            }
+        }
+    }
+    return {
+        attachmentsTree,
+        selectedNode,
+        errorList,
+        currentErrors,
+        currentWarnings
+    };
 };
 
-const mapActionsToProps = (dispatch) => {
-       return {
-               toggleExpanded: (path) => HeatValidationActionHelper.toggleExpanded(dispatch, {path}),
-               onSelectNode: (nodeName) => HeatValidationActionHelper.onSelectNode(dispatch, {nodeName}),
-               onDeselectNode: () => HeatValidationActionHelper.onDeselectNode(dispatch)
-       };
+const mapActionsToProps = dispatch => {
+    return {
+        toggleExpanded: path =>
+            HeatValidationActionHelper.toggleExpanded(dispatch, { path }),
+        onSelectNode: nodeName =>
+            HeatValidationActionHelper.onSelectNode(dispatch, { nodeName }),
+        onDeselectNode: () =>
+            HeatValidationActionHelper.onDeselectNode(dispatch)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(HeatValidationView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(HeatValidationView);
index 73366c2..5e8e49c 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './HeatValidationConstants.js';
+import { actionTypes } from './HeatValidationConstants.js';
 
 export default {
+    toggleExpanded(dispatch, { path }) {
+        dispatch({
+            type: actionTypes.TOGGLE_EXPANDED,
+            path
+        });
+    },
 
-       toggleExpanded(dispatch, {path}) {
-               dispatch({
-                       type: actionTypes.TOGGLE_EXPANDED,
-                       path
-               });
-       },
+    onSelectNode(dispatch, { nodeName }) {
+        dispatch({
+            type: actionTypes.SELECTED_NODE,
+            nodeName
+        });
+    },
 
-       onSelectNode(dispatch, {nodeName}) {
-               dispatch({
-                       type: actionTypes.SELECTED_NODE,
-                       nodeName
-               });
-       },
-
-       onDeselectNode(dispatch) {
-               dispatch({
-                       type: actionTypes.UNSELECTED_NODE
-               });
-       }
+    onDeselectNode(dispatch) {
+        dispatch({
+            type: actionTypes.UNSELECTED_NODE
+        });
+    }
 };
index f783fe6..8c9f54b 100644 (file)
@@ -17,41 +17,48 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 export const actionTypes = keyMirror({
-       TOGGLE_EXPANDED: null,
-       SELECTED_NODE: null,
-       UNSELECTED_NODE: null
+    TOGGLE_EXPANDED: null,
+    SELECTED_NODE: null,
+    UNSELECTED_NODE: null
 });
 
 export const errorTypes = keyMirror({
-       MISSING_FILE_IN_ZIP: i18n('missing file in zip'),
-       MISSING_FILE_IN_MANIFEST: i18n('missing file in manifest'),
-       MISSING_OR_ILLEGAL_FILE_TYPE_IN_MANIFEST: i18n('missing or illegal file type in manifest'),
-       FILE_IS_YML_WITHOUT_YML_EXTENSION: i18n('file is defined as a heat file but it doesn\'t have .yml or .yaml extension'),
-       FILE_IS_ENV_WITHOUT_ENV_EXTENSION: i18n('file is defined as an env file but it doesn\'t have .env extension'),
-       ILLEGAL_YAML_FILE_CONTENT: i18n('illegal yaml file content'),
-       ILLEGAL_HEAT_YAML_FILE_CONTENT: i18n('illegal HEAT yaml file content'),
-       MISSING_FILE_NAME_IN_MANIFEST: i18n('a file is written in manifest without file name'),
-       MISSING_ENV_FILE_IN_ZIP: i18n('missing env file in zip'),
-       ARTIFACT_NOT_IN_USE: i18n('artifact not in use')
+    MISSING_FILE_IN_ZIP: i18n('missing file in zip'),
+    MISSING_FILE_IN_MANIFEST: i18n('missing file in manifest'),
+    MISSING_OR_ILLEGAL_FILE_TYPE_IN_MANIFEST: i18n(
+        'missing or illegal file type in manifest'
+    ),
+    FILE_IS_YML_WITHOUT_YML_EXTENSION: i18n(
+        "file is defined as a heat file but it doesn't have .yml or .yaml extension"
+    ),
+    FILE_IS_ENV_WITHOUT_ENV_EXTENSION: i18n(
+        "file is defined as an env file but it doesn't have .env extension"
+    ),
+    ILLEGAL_YAML_FILE_CONTENT: i18n('illegal yaml file content'),
+    ILLEGAL_HEAT_YAML_FILE_CONTENT: i18n('illegal HEAT yaml file content'),
+    MISSING_FILE_NAME_IN_MANIFEST: i18n(
+        'a file is written in manifest without file name'
+    ),
+    MISSING_ENV_FILE_IN_ZIP: i18n('missing env file in zip'),
+    ARTIFACT_NOT_IN_USE: i18n('artifact not in use')
 });
 
 export const errorLevels = keyMirror({
-       WARNING: 'WARNING',
-       ERROR: 'ERROR'
+    WARNING: 'WARNING',
+    ERROR: 'ERROR'
 });
 export const nodeFilters = keyMirror({
-       ALL: 'All'
+    ALL: 'All'
 });
 export const nodeTypes = keyMirror({
-       heat: i18n('Heat'),
-       volume: i18n('Volume'),
-       network: i18n('Network'),
-       artifact: i18n('Artifact'),
-       env: i18n('Environment'),
-       other: i18n('')
+    heat: i18n('Heat'),
+    volume: i18n('Volume'),
+    network: i18n('Network'),
+    artifact: i18n('Artifact'),
+    env: i18n('Environment'),
+    other: i18n('')
 });
 
 export const mouseActions = keyMirror({
-       MOUSE_BUTTON_CLICK: 0
+    MOUSE_BUTTON_CLICK: 0
 });
-
index 1d11bdd..67e36ca 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes as softwareProductsActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-import {actionTypes, nodeFilters} from './HeatValidationConstants.js';
+import { actionTypes as softwareProductsActionTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { actionTypes, nodeFilters } from './HeatValidationConstants.js';
 
-const mapVolumeData = ({fileName, env, errors}) => ({
-       name: fileName,
-       expanded: true,
-       type: 'volume',
-       children: env && [{
-               name: env.fileName,
-               errors: env.errors,
-               type: 'env'
-       }],
-       errors
+const mapVolumeData = ({ fileName, env, errors }) => ({
+    name: fileName,
+    expanded: true,
+    type: 'volume',
+    children: env && [
+        {
+            name: env.fileName,
+            errors: env.errors,
+            type: 'env'
+        }
+    ],
+    errors
 });
 
-const mapNetworkData = ({fileName, env, errors}) => ({
-       name: fileName,
-       expanded: true,
-       type: 'network',
-       children: env && [{
-               name: env.fileName,
-               errors: env.errors,
-               type: 'env'
-       }],
-       errors
+const mapNetworkData = ({ fileName, env, errors }) => ({
+    name: fileName,
+    expanded: true,
+    type: 'network',
+    children: env && [
+        {
+            name: env.fileName,
+            errors: env.errors,
+            type: 'env'
+        }
+    ],
+    errors
 });
 
-const mapArtifactsData = ({fileName, errors}) => ({
-       name: fileName,
-       type: 'artifact',
-       errors
+const mapArtifactsData = ({ fileName, errors }) => ({
+    name: fileName,
+    type: 'artifact',
+    errors
 });
 
-const mapOtherData = ({fileName, errors}) => ({
-       name: fileName,
-       type: 'other',
-       errors
+const mapOtherData = ({ fileName, errors }) => ({
+    name: fileName,
+    type: 'other',
+    errors
 });
 
-
-const mapHeatData = ({fileName, env, nested, volume, network, artifacts, errors, other}) => ({
-       name: fileName,
-       expanded: true,
-       type: 'heat',
-       errors,
-       children: [
-               ...(volume ? volume.map(mapVolumeData) : []),
-               ...(network ? network.map(mapNetworkData) : []),
-               ...(env ? [{
-                       name: env.fileName,
-                       errors: env.errors,
-                       type: 'env'
-               }] : []),
-               ...(artifacts ? artifacts.map(mapArtifactsData) : []),
-               ...(other ? other.map(mapOtherData) : []),
-               ...(nested ? nested.map(mapHeatData) : [])
-       ]
+const mapHeatData = ({
+    fileName,
+    env,
+    nested,
+    volume,
+    network,
+    artifacts,
+    errors,
+    other
+}) => ({
+    name: fileName,
+    expanded: true,
+    type: 'heat',
+    errors,
+    children: [
+        ...(volume ? volume.map(mapVolumeData) : []),
+        ...(network ? network.map(mapNetworkData) : []),
+        ...(env
+            ? [
+                  {
+                      name: env.fileName,
+                      errors: env.errors,
+                      type: 'env'
+                  }
+              ]
+            : []),
+        ...(artifacts ? artifacts.map(mapArtifactsData) : []),
+        ...(other ? other.map(mapOtherData) : []),
+        ...(nested ? nested.map(mapHeatData) : [])
+    ]
 });
 
 function createErrorList(node, parent, deep = 0, errorList = []) {
-       if (node.errors) {
-               errorList.push(...node.errors.map((error) => ({
-                       level: error.level,
-                       errorMessage: error.message,
-                       name: node.name,
-                       hasParent: deep > 2,
-                       parentName: parent.name,
-                       type: node.type,
-               })));
-       }
-       if (node.children && node.children.length) {
-               node.children.map((child) => createErrorList(child, node, deep + 1, errorList));
-       }
-       return errorList;
+    if (node.errors) {
+        errorList.push(
+            ...node.errors.map(error => ({
+                level: error.level,
+                errorMessage: error.message,
+                name: node.name,
+                hasParent: deep > 2,
+                parentName: parent.name,
+                type: node.type
+            }))
+        );
+    }
+    if (node.children && node.children.length) {
+        node.children.map(child =>
+            createErrorList(child, node, deep + 1, errorList)
+        );
+    }
+    return errorList;
 }
 
 const mapValidationDataToTree = (validationData, packageName) => {
-       let {heat, nested, volume, network, artifacts, other} = validationData.importStructure || {};
-       return {
-               children: [
-                       {
-                               name: packageName,
-                               expanded: true,
-                               type: 'heat',
-                               header: true,
-                               children: (heat ? heat.map(mapHeatData) : nested ? nested.map(mapHeatData) : [])
-                       },
-                       ...(artifacts ? [{
-                               name: 'artifacts',
-                               expanded: true,
-                               type: 'artifact',
-                               children: (artifacts ? artifacts.map(mapArtifactsData) : [])
-                       }] : []),
-                       ...(network ? [{
-                               name: 'networks',
-                               expanded: true,
-                               type: 'network',
-                               children: (network ? network.map(mapNetworkData) : []),
-                       }] : []),
-                       ...(volume ? [{
-                               name: 'volume',
-                               expanded: true,
-                               type: 'volume',
-                               children: (volume ? volume.map(mapVolumeData) : []),
-                       }] : []),
-                       ...(other ? [{
-                               name: 'other',
-                               expanded: true,
-                               type: 'other',
-                               children: (other ? other.map(mapOtherData) : []),
-                       }] : [])
-               ]
-       };
+    let { heat, nested, volume, network, artifacts, other } =
+        validationData.importStructure || {};
+    return {
+        children: [
+            {
+                name: packageName,
+                expanded: true,
+                type: 'heat',
+                header: true,
+                children: heat
+                    ? heat.map(mapHeatData)
+                    : nested ? nested.map(mapHeatData) : []
+            },
+            ...(artifacts
+                ? [
+                      {
+                          name: 'artifacts',
+                          expanded: true,
+                          type: 'artifact',
+                          children: artifacts
+                              ? artifacts.map(mapArtifactsData)
+                              : []
+                      }
+                  ]
+                : []),
+            ...(network
+                ? [
+                      {
+                          name: 'networks',
+                          expanded: true,
+                          type: 'network',
+                          children: network ? network.map(mapNetworkData) : []
+                      }
+                  ]
+                : []),
+            ...(volume
+                ? [
+                      {
+                          name: 'volume',
+                          expanded: true,
+                          type: 'volume',
+                          children: volume ? volume.map(mapVolumeData) : []
+                      }
+                  ]
+                : []),
+            ...(other
+                ? [
+                      {
+                          name: 'other',
+                          expanded: true,
+                          type: 'other',
+                          children: other ? other.map(mapOtherData) : []
+                      }
+                  ]
+                : [])
+        ]
+    };
 };
 
 const toggleExpanded = (node, path) => {
-       let newNode = {...node};
-       if (path.length === 0) {
-               newNode.expanded = !node.expanded;
-       } else {
-               let index = path[0];
-               newNode.children = [
-                       ...node.children.slice(0, index),
-                       toggleExpanded(node.children[index], path.slice(1)),
-                       ...node.children.slice(index + 1)
-               ];
-       }
-       return newNode;
+    let newNode = { ...node };
+    if (path.length === 0) {
+        newNode.expanded = !node.expanded;
+    } else {
+        let index = path[0];
+        newNode.children = [
+            ...node.children.slice(0, index),
+            toggleExpanded(node.children[index], path.slice(1)),
+            ...node.children.slice(index + 1)
+        ];
+    }
+    return newNode;
 };
 
 const expandSelected = (node, selectedNode) => {
-       let shouldExpand = node.name === selectedNode;
-       let children = node.children && node.children.map(child => {
-               let {shouldExpand: shouldExpandChild, node: newChild} = expandSelected(child, selectedNode);
-               shouldExpand = shouldExpand || shouldExpandChild;
-               return newChild;
-       });
+    let shouldExpand = node.name === selectedNode;
+    let children =
+        node.children &&
+        node.children.map(child => {
+            let {
+                shouldExpand: shouldExpandChild,
+                node: newChild
+            } = expandSelected(child, selectedNode);
+            shouldExpand = shouldExpand || shouldExpandChild;
+            return newChild;
+        });
 
-       return {
-               node: {
-                       ...node,
-                       expanded: node.expanded || shouldExpand,
-                       children
-               },
-               shouldExpand
-       };
+    return {
+        node: {
+            ...node,
+            expanded: node.expanded || shouldExpand,
+            children
+        },
+        shouldExpand
+    };
 };
 
-export default (state = {attachmentsTree: {}}, action) => {
-       switch (action.type) {
-               case softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED:
-                       let currentSoftwareProduct = action.response;
-                       const packageName = currentSoftwareProduct.networkPackageName;
-                       let attachmentsTree = currentSoftwareProduct.validationData ? mapValidationDataToTree(currentSoftwareProduct.validationData, packageName) : {};
-                       let errorList = createErrorList(attachmentsTree);
-                       return {
-                               ...state,
-                               attachmentsTree,
-                               errorList,
-                               selectedNode: nodeFilters.ALL
-                       };
-               case actionTypes.TOGGLE_EXPANDED:
-                       return {
-                               ...state,
-                               attachmentsTree: toggleExpanded(state.attachmentsTree, action.path)
-                       };
-               case actionTypes.SELECTED_NODE:
-                       let selectedNode = action.nodeName;
-                       return {
-                               ...state,
-                               attachmentsTree: expandSelected(state.attachmentsTree, selectedNode).node,
-                               selectedNode
-                       };
-               case actionTypes.UNSELECTED_NODE:
-                       return {
-                               ...state,
-                               selectedNode: nodeFilters.ALL
-                       };
-               default:
-                       return state;
-       }
+export default (state = { attachmentsTree: {} }, action) => {
+    switch (action.type) {
+        case softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED:
+            let currentSoftwareProduct = action.response;
+            const packageName = currentSoftwareProduct.networkPackageName;
+            let attachmentsTree = currentSoftwareProduct.validationData
+                ? mapValidationDataToTree(
+                      currentSoftwareProduct.validationData,
+                      packageName
+                  )
+                : {};
+            let errorList = createErrorList(attachmentsTree);
+            return {
+                ...state,
+                attachmentsTree,
+                errorList,
+                selectedNode: nodeFilters.ALL
+            };
+        case actionTypes.TOGGLE_EXPANDED:
+            return {
+                ...state,
+                attachmentsTree: toggleExpanded(
+                    state.attachmentsTree,
+                    action.path
+                )
+            };
+        case actionTypes.SELECTED_NODE:
+            let selectedNode = action.nodeName;
+            return {
+                ...state,
+                attachmentsTree: expandSelected(
+                    state.attachmentsTree,
+                    selectedNode
+                ).node,
+                selectedNode
+            };
+        case actionTypes.UNSELECTED_NODE:
+            return {
+                ...state,
+                selectedNode: nodeFilters.ALL
+            };
+        default:
+            return state;
+    }
 };
index 3fdaa9c..c6ee5ef 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import Collapse from 'react-bootstrap/lib/Collapse.js';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {mouseActions, errorLevels, nodeFilters} from './HeatValidationConstants.js';
+import {
+    mouseActions,
+    errorLevels,
+    nodeFilters
+} from './HeatValidationConstants.js';
 
 const leftPanelWidth = 250;
 const typeToIcon = Object.freeze({
-       heat: 'nestedHeat',
-       volume: 'base',
-       network: 'network',
-       artifact: 'artifacts',
-       env: 'env',
-       other: 'other'
+    heat: 'nestedHeat',
+    volume: 'base',
+    network: 'network',
+    artifact: 'artifacts',
+    env: 'env',
+    other: 'other'
 });
 
-
 class HeatValidationView extends Component {
+    static propTypes = {
+        attachmentsTree: PropTypes.object.isRequired,
+        errorList: PropTypes.array.isRequired,
+        currentErrors: PropTypes.array.isRequired,
+        currentWarnings: PropTypes.array.isRequired,
+        onSelectNode: PropTypes.func.isRequired,
+        onDeselectNode: PropTypes.func.isRequired,
+        toggleExpanded: PropTypes.func.isRequired,
+        selectedNode: PropTypes.string
+    };
 
-       static propTypes = {
-               attachmentsTree: PropTypes.object.isRequired,
-               errorList: PropTypes.array.isRequired,
-               currentErrors: PropTypes.array.isRequired,
-               currentWarnings: PropTypes.array.isRequired,
-               onSelectNode: PropTypes.func.isRequired,
-               onDeselectNode: PropTypes.func.isRequired,
-               toggleExpanded: PropTypes.func.isRequired,
-               selectedNode: PropTypes.string
-       };
-
-       render() {
-               return (<div className='vsp-attachments-heat-validation' data-test-id='heat-validation-editor'>
-                       <HeatFileTree errorList={this.props.errorList} attachmentsTree={this.props.attachmentsTree}
-                               onSelectNode={this.props.onSelectNode} toggleExpanded={this.props.toggleExpanded}
-                               selectedNode={this.props.selectedNode} onDeselectNode={this.props.onDeselectNode} />
-                       <HeatMessageBoard errors={this.props.currentErrors} warnings={this.props.currentWarnings} selectedNode={this.props.selectedNode} />
-               </div> );
-       }
+    render() {
+        return (
+            <div
+                className="vsp-attachments-heat-validation"
+                data-test-id="heat-validation-editor">
+                <HeatFileTree
+                    errorList={this.props.errorList}
+                    attachmentsTree={this.props.attachmentsTree}
+                    onSelectNode={this.props.onSelectNode}
+                    toggleExpanded={this.props.toggleExpanded}
+                    selectedNode={this.props.selectedNode}
+                    onDeselectNode={this.props.onDeselectNode}
+                />
+                <HeatMessageBoard
+                    errors={this.props.currentErrors}
+                    warnings={this.props.currentWarnings}
+                    selectedNode={this.props.selectedNode}
+                />
+            </div>
+        );
+    }
 }
 
 function HeatFileTreeRow(props) {
-       let {node, path, toggleExpanded, selectedNode, selectNode} = props;
-       let isFolder = node.children && node.children.length > 0;
-       return (
-               <div onDoubleClick={() => toggleExpanded(path)} className={classNames({
-                       'tree-node-row': true,
-                       'tree-node-clicked': node.name === props.selectedNode
-               })} data-test-id='validation-tree-node'>
-                       <div className='name-section'>
-                               {
-                                       isFolder &&
-                                               <div onClick={() => toggleExpanded(path)}
-                                                       className='tree-node-expander'>
-                                                       <SVGIcon name={!node.expanded ? 'chevronUp' : 'chevronDown'} data-test-id='validation-tree-block-toggle'/>
-                                               </div>
-                               }
-                               {
-
-                                       <span className='tree-node-icon'>
-                                               <SVGIcon name={typeToIcon[node.type]} color={selectedNode === node.name ? 'primary' : 'secondary'}/>
-                                       </span>
-                               }
-                               {
-
-                                       <span  className='tree-node-name' onClick={() => selectNode(node.name)} data-test-id='validation-tree-node-name'>
-                                               {node.name ? node.name : 'UNKNOWN'}
-                                       </span>
-                               }
-                       </div>
-                       <ErrorsAndWarningsCount errorList={node.errors} onClick={() => selectNode(node.name)} />
-               </div>);
+    let { node, path, toggleExpanded, selectedNode, selectNode } = props;
+    let isFolder = node.children && node.children.length > 0;
+    return (
+        <div
+            onDoubleClick={() => toggleExpanded(path)}
+            className={classNames({
+                'tree-node-row': true,
+                'tree-node-clicked': node.name === props.selectedNode
+            })}
+            data-test-id="validation-tree-node">
+            <div className="name-section">
+                {isFolder && (
+                    <div
+                        onClick={() => toggleExpanded(path)}
+                        className="tree-node-expander">
+                        <SVGIcon
+                            name={!node.expanded ? 'chevronUp' : 'chevronDown'}
+                            data-test-id="validation-tree-block-toggle"
+                        />
+                    </div>
+                )}
+                {
+                    <span className="tree-node-icon">
+                        <SVGIcon
+                            name={typeToIcon[node.type]}
+                            color={
+                                selectedNode === node.name
+                                    ? 'primary'
+                                    : 'secondary'
+                            }
+                        />
+                    </span>
+                }
+                {
+                    <span
+                        className="tree-node-name"
+                        onClick={() => selectNode(node.name)}
+                        data-test-id="validation-tree-node-name">
+                        {node.name ? node.name : 'UNKNOWN'}
+                    </span>
+                }
+            </div>
+            <ErrorsAndWarningsCount
+                errorList={node.errors}
+                onClick={() => selectNode(node.name)}
+            />
+        </div>
+    );
 }
 
 function HeatFileTreeHeader(props) {
-       let hasErrors = props.errorList.filter(error => error.level === errorLevels.ERROR).length > 0;
-       return (
-               <div onClick={() => props.selectNode(nodeFilters.ALL)} className={classNames({'attachments-tree-header': true,
-                       'header-selected' : props.selectedNode === nodeFilters.ALL})} data-test-id='validation-tree-header'>
-                       <div className='tree-header-title' >
-                               {/*<SVGIcon name='zip' color={props.selectedNode === nodeFilters.ALL ? 'primary' : ''}  iconClassName='header-icon' />*/}
-                               <span className={classNames({'tree-header-title-text' : true,
-                                       'tree-header-title-selected' : props.selectedNode === nodeFilters.ALL})}>{i18n('{title} {hasErrors}', {title: props.headerTitle, hasErrors: hasErrors ? '(Draft)' : ''})}</span>
-                       </div>
-                       <ErrorsAndWarningsCount errorList={props.errorList} size='large' />
-               </div>);
+    let hasErrors =
+        props.errorList.filter(error => error.level === errorLevels.ERROR)
+            .length > 0;
+    return (
+        <div
+            onClick={() => props.selectNode(nodeFilters.ALL)}
+            className={classNames({
+                'attachments-tree-header': true,
+                'header-selected': props.selectedNode === nodeFilters.ALL
+            })}
+            data-test-id="validation-tree-header">
+            <div className="tree-header-title">
+                {/*<SVGIcon name='zip' color={props.selectedNode === nodeFilters.ALL ? 'primary' : ''}  iconClassName='header-icon' />*/}
+                <span
+                    className={classNames({
+                        'tree-header-title-text': true,
+                        'tree-header-title-selected':
+                            props.selectedNode === nodeFilters.ALL
+                    })}>
+                    {i18n('{title} {hasErrors}', {
+                        title: props.headerTitle,
+                        hasErrors: hasErrors ? '(Draft)' : ''
+                    })}
+                </span>
+            </div>
+            <ErrorsAndWarningsCount errorList={props.errorList} size="large" />
+        </div>
+    );
 }
 
-class HeatFileTree extends React.Component  {
-       static propTypes = {
-               attachmentsTree: PropTypes.object.isRequired,
-               errorList: PropTypes.array.isRequired,
-               onSelectNode: PropTypes.func.isRequired,
-               onDeselectNode: PropTypes.func.isRequired,
-               toggleExpanded: PropTypes.func.isRequired,
-               selectedNode: PropTypes.string
-       };
-       state = {
-               treeWidth: '400'
-       };
-       render() {
-               let {attachmentsTree} = this.props;
-               return (
-                       <div className='validation-tree-section' style={{'width' : this.state.treeWidth + 'px'}}>
-                               <div className='vsp-attachments-heat-validation-tree'>
-                                       <div className='tree-wrapper'>
-                                               {attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind]))}
-                                       </div>
-                               </div>
-                               <div onMouseDown={(e) => this.onChangeTreeWidth(e)}
-                                        className='vsp-attachments-heat-validation-separator' data-test-id='validation-tree-separator'></div>
-                       </div>);
-       }
-       renderNode(node, path) {
-               let rand = Math.random() * (3000 - 1) + 1;
-               let isFolder = node.children && node.children.length > 0;
-               let {selectedNode} = this.props;
-               return (
-                       <div key={node.name + rand} className={classNames({'tree-block-inside' : !node.header})}>
-                               {
-                                       node.header ?
-                                       <HeatFileTreeHeader headerTitle={node.name} selectedNode={selectedNode} errorList={this.props.errorList} selectNode={(nodeName) => this.selectNode(nodeName)}  /> :
-                                       <HeatFileTreeRow toggleExpanded={this.props.toggleExpanded} node={node} path={path} selectedNode={selectedNode} selectNode={() => this.selectNode(node.name)} />
-                               }
-                               {
-                                       isFolder &&
-                                       <Collapse in={node.expanded}>
-                                               <div className='tree-node-children'>
-                                                       {
-                                                               node.children.map((child, ind) => this.renderNode(child, [...path, ind]))
-                                                       }
-                                               </div>
-                                       </Collapse>
-                               }
-                       </div>
-               );
-       }
-
-
-
-
-
-       selectNode(currentSelectedNode) {
-               let {onDeselectNode, onSelectNode, selectedNode} = this.props;
-               if (currentSelectedNode !== selectedNode) {
-                       onSelectNode(currentSelectedNode);
-               } else {
-                       onDeselectNode();
-               }
-
-
+class HeatFileTree extends React.Component {
+    static propTypes = {
+        attachmentsTree: PropTypes.object.isRequired,
+        errorList: PropTypes.array.isRequired,
+        onSelectNode: PropTypes.func.isRequired,
+        onDeselectNode: PropTypes.func.isRequired,
+        toggleExpanded: PropTypes.func.isRequired,
+        selectedNode: PropTypes.string
+    };
+    state = {
+        treeWidth: '400'
+    };
+    render() {
+        let { attachmentsTree } = this.props;
+        return (
+            <div
+                className="validation-tree-section"
+                style={{ width: this.state.treeWidth + 'px' }}>
+                <div className="vsp-attachments-heat-validation-tree">
+                    <div className="tree-wrapper">
+                        {attachmentsTree &&
+                            attachmentsTree.children &&
+                            attachmentsTree.children.map((child, ind) =>
+                                this.renderNode(child, [ind])
+                            )}
+                    </div>
+                </div>
+                <div
+                    onMouseDown={e => this.onChangeTreeWidth(e)}
+                    className="vsp-attachments-heat-validation-separator"
+                    data-test-id="validation-tree-separator"
+                />
+            </div>
+        );
+    }
+    renderNode(node, path) {
+        let rand = Math.random() * (3000 - 1) + 1;
+        let isFolder = node.children && node.children.length > 0;
+        let { selectedNode } = this.props;
+        return (
+            <div
+                key={node.name + rand}
+                className={classNames({ 'tree-block-inside': !node.header })}>
+                {node.header ? (
+                    <HeatFileTreeHeader
+                        headerTitle={node.name}
+                        selectedNode={selectedNode}
+                        errorList={this.props.errorList}
+                        selectNode={nodeName => this.selectNode(nodeName)}
+                    />
+                ) : (
+                    <HeatFileTreeRow
+                        toggleExpanded={this.props.toggleExpanded}
+                        node={node}
+                        path={path}
+                        selectedNode={selectedNode}
+                        selectNode={() => this.selectNode(node.name)}
+                    />
+                )}
+                {isFolder && (
+                    <Collapse in={node.expanded}>
+                        <div className="tree-node-children">
+                            {node.children.map((child, ind) =>
+                                this.renderNode(child, [...path, ind])
+                            )}
+                        </div>
+                    </Collapse>
+                )}
+            </div>
+        );
+    }
 
-       }
+    selectNode(currentSelectedNode) {
+        let { onDeselectNode, onSelectNode, selectedNode } = this.props;
+        if (currentSelectedNode !== selectedNode) {
+            onSelectNode(currentSelectedNode);
+        } else {
+            onDeselectNode();
+        }
+    }
 
-       onChangeTreeWidth(e) {
-               if (e.button === mouseActions.MOUSE_BUTTON_CLICK) {
-                       let onMouseMove = (e) => {
-                               this.setState({treeWidth: e.clientX - leftPanelWidth});
-                       };
-                       let onMouseUp = () => {
-                               document.removeEventListener('mousemove', onMouseMove);
-                               document.removeEventListener('mouseup', onMouseUp);
-                       };
-                       document.addEventListener('mousemove', onMouseMove);
-                       document.addEventListener('mouseup', onMouseUp);
-               }
-       }
+    onChangeTreeWidth(e) {
+        if (e.button === mouseActions.MOUSE_BUTTON_CLICK) {
+            let onMouseMove = e => {
+                this.setState({ treeWidth: e.clientX - leftPanelWidth });
+            };
+            let onMouseUp = () => {
+                document.removeEventListener('mousemove', onMouseMove);
+                document.removeEventListener('mouseup', onMouseUp);
+            };
+            document.addEventListener('mousemove', onMouseMove);
+            document.addEventListener('mouseup', onMouseUp);
+        }
+    }
 }
 
 class HeatMessageBoard extends Component {
-       static propTypes = {
-               currentErrors: PropTypes.array,
-               currentWarnings: PropTypes.array,
-               selectedNode: PropTypes.string
-       };
-       render() {
-               let {errors, warnings} = this.props;
-               let allItems = [...errors, ...warnings];
-               return (
-                       <div className='message-board-section'>
-                               { allItems.map(error => this.renderError(error)) }
-                       </div>
-               );
-       }
-       renderError(error) {
-               let rand = Math.random() * (3000 - 1) + 1;
-               return (
-                       <div
-                               key={error.name + error.errorMessage + error.parentName + rand}
-                               className='error-item' data-test-id='validation-error'>
-                               {error.level === errorLevels.WARNING ?
-                                       <SVGIcon name='exclamationTriangleLine' iconClassName='large' color='warning' /> : <SVGIcon name='error' iconClassName='large' color='negative' /> }
-                               <span className='error-item-file-type'>
-                               {
-                                       (this.props.selectedNode === nodeFilters.ALL) ?
-                                               <span>
-                                                       <span className='error-file-name'>
-                                                               {error.name}
-                                                       </span>
-                                                       <span>
-                                                               {error.errorMessage}
-                                                       </span>
-                                               </span> :
-                                               error.errorMessage
-                               }
-                               </span>
-                       </div>
-               );
-       }
+    static propTypes = {
+        currentErrors: PropTypes.array,
+        currentWarnings: PropTypes.array,
+        selectedNode: PropTypes.string
+    };
+    render() {
+        let { errors, warnings } = this.props;
+        let allItems = [...errors, ...warnings];
+        return (
+            <div className="message-board-section">
+                {allItems.map(error => this.renderError(error))}
+            </div>
+        );
+    }
+    renderError(error) {
+        let rand = Math.random() * (3000 - 1) + 1;
+        return (
+            <div
+                key={error.name + error.errorMessage + error.parentName + rand}
+                className="error-item"
+                data-test-id="validation-error">
+                {error.level === errorLevels.WARNING ? (
+                    <SVGIcon
+                        name="exclamationTriangleLine"
+                        iconClassName="large"
+                        color="warning"
+                    />
+                ) : (
+                    <SVGIcon
+                        name="error"
+                        iconClassName="large"
+                        color="negative"
+                    />
+                )}
+                <span className="error-item-file-type">
+                    {this.props.selectedNode === nodeFilters.ALL ? (
+                        <span>
+                            <span className="error-file-name">
+                                {error.name}
+                            </span>
+                            <span>{error.errorMessage}</span>
+                        </span>
+                    ) : (
+                        error.errorMessage
+                    )}
+                </span>
+            </div>
+        );
+    }
 }
 class ErrorsAndWarningsCount extends Component {
-       static propTypes = {
-               errorList: PropTypes.array,
-               size: PropTypes.string
-       };
-       render() {
-               let errors = this.getErrorsAndWarningsCount(this.props.errorList);
-               if (!errors) {
-                       return null;
-               }
-               let {size} = this.props;
-               return (<div className='counters'>
-                       {(errors.errorCount > 0) && <div className='counter'>
-                               <SVGIcon name='error' color='negative' iconClassName={size}/>
-                               <div className={'error-text ' + (size ? size : '')} data-test-id='validation-error-count'>{errors.errorCount}</div>
-                       </div>}
-                       {(errors.warningCount > 0) && <div className='counter'>
-                               <SVGIcon name='exclamationTriangleLine' iconClassName={size} color='warning'/>
-                               <div className={'warning-text ' + (size ? size : '')} data-test-id='validation-warning-count'>{errors.warningCount}</div>
-                       </div>}
-               </div>);
-       }
-       getErrorsAndWarningsCount(errorList) {
-               let errorCount = 0, warningCount = 0;
-               if (errorList && errorList.length > 0) {
-                       for (let i = 0; i < errorList.length; i++) {
-                               if (errorList[i].level === errorLevels.ERROR) {
-                                       errorCount++;
-                               } else if (errorList[i].level === errorLevels.WARNING) {
-                                       warningCount++;
-                               }
-                       }
-               }
-               if (errorCount === 0 && warningCount === 0) {
-                       return null;
-               }
-               return {errorCount, warningCount};
-       }
+    static propTypes = {
+        errorList: PropTypes.array,
+        size: PropTypes.string
+    };
+    render() {
+        let errors = this.getErrorsAndWarningsCount(this.props.errorList);
+        if (!errors) {
+            return null;
+        }
+        let { size } = this.props;
+        return (
+            <div className="counters">
+                {errors.errorCount > 0 && (
+                    <div className="counter">
+                        <SVGIcon
+                            name="error"
+                            color="negative"
+                            iconClassName={size}
+                        />
+                        <div
+                            className={'error-text ' + (size ? size : '')}
+                            data-test-id="validation-error-count">
+                            {errors.errorCount}
+                        </div>
+                    </div>
+                )}
+                {errors.warningCount > 0 && (
+                    <div className="counter">
+                        <SVGIcon
+                            name="exclamationTriangleLine"
+                            iconClassName={size}
+                            color="warning"
+                        />
+                        <div
+                            className={'warning-text ' + (size ? size : '')}
+                            data-test-id="validation-warning-count">
+                            {errors.warningCount}
+                        </div>
+                    </div>
+                )}
+            </div>
+        );
+    }
+    getErrorsAndWarningsCount(errorList) {
+        let errorCount = 0,
+            warningCount = 0;
+        if (errorList && errorList.length > 0) {
+            for (let i = 0; i < errorList.length; i++) {
+                if (errorList[i].level === errorLevels.ERROR) {
+                    errorCount++;
+                } else if (errorList[i].level === errorLevels.WARNING) {
+                    warningCount++;
+                }
+            }
+        }
+        if (errorCount === 0 && warningCount === 0) {
+            return null;
+        }
+        return { errorCount, warningCount };
+    }
 }
 export default HeatValidationView;
index b13bde0..e59337c 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, forms} from './SoftwareProductComponentsConstants.js';
+import { actionTypes, forms } from './SoftwareProductComponentsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.COMPONENT_CREATE_OPEN: 
-                       return {
-                               ...state,
-                               formName: forms.CREATE_FORM,
-                               formReady: null,
-                               genericFieldInfo: {
-                                       'displayName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'validateName', data: true}, {type: 'maxLength', data: 25}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       }
-                               }
-                       };
-               case actionTypes.COMPONENT_LOAD:
-                       return {
-                               ...state,
-                               data: action.component,
-                               formReady: null,
-                               formName: forms.ALL_SPC_FORMS,
-                               genericFieldInfo: {
-                                       'displayName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'vfcCode' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'nfcFunction' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 30}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               }
-                       };
-               case actionTypes.COMPONENT_UPDATE:
-                       return {
-                               ...state,
-                               data: action.component
-                       };
-               case actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE:
-                       return {
-                               ...state,
-                               qdata: action.payload.qdata || state.qdata,
-                               qschema: action.payload.qschema || state.qschema
-                       };
-               case actionTypes.COMPONENT_DATA_CHANGED:
-                       return {
-                               ...state,
-                               data: {
-                                       ...state.data,
-                                       ...action.deltaData
-                               }
-                       };
-               case actionTypes.COMPONENT_DATA_CLEAR:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.COMPONENT_CREATE_OPEN:
+            return {
+                ...state,
+                formName: forms.CREATE_FORM,
+                formReady: null,
+                genericFieldInfo: {
+                    displayName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'validateName', data: true },
+                            { type: 'maxLength', data: 25 }
+                        ]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    }
+                }
+            };
+        case actionTypes.COMPONENT_LOAD:
+            return {
+                ...state,
+                data: action.component,
+                formReady: null,
+                formName: forms.ALL_SPC_FORMS,
+                genericFieldInfo: {
+                    displayName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    vfcCode: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    nfcFunction: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 30 }]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                }
+            };
+        case actionTypes.COMPONENT_UPDATE:
+            return {
+                ...state,
+                data: action.component
+            };
+        case actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE:
+            return {
+                ...state,
+                qdata: action.payload.qdata || state.qdata,
+                qschema: action.payload.qschema || state.qschema
+            };
+        case actionTypes.COMPONENT_DATA_CHANGED:
+            return {
+                ...state,
+                data: {
+                    ...state.data,
+                    ...action.deltaData
+                }
+            };
+        case actionTypes.COMPONENT_DATA_CLEAR:
+            return {};
+        default:
+            return state;
+    }
 };
index f74b2fe..bffa9f7 100644 (file)
@@ -1,50 +1,71 @@
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 import SoftwareProductComponentsActionHelper from '../components/SoftwareProductComponentsActionHelper.js';
-import {onboardingMethod as onboardingMethodTypes} from '../SoftwareProductConstants.js';
+import { onboardingMethod as onboardingMethodTypes } from '../SoftwareProductConstants.js';
 import ConfirmationModalConstants from 'nfvo-components/modal/GlobalModalConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import SoftwareProductComponentsView from './SoftwareProductComponentsListView.jsx';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 
-const generateMessage = (name) => {
-       return i18n('Are you sure you want to delete {name}?', {name: name});
+const generateMessage = name => {
+    return i18n('Are you sure you want to delete {name}?', { name: name });
 };
 
-const mapStateToProps = ({softwareProduct, currentScreen: {props: {version}}}) => {
-       let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductComponents} = softwareProduct;
-       let {componentsList} = softwareProductComponents;
-       let {onboardingMethod = onboardingMethodTypes.HEAT} = currentSoftwareProduct;
-       return {
-               currentSoftwareProduct,
-               componentsList,
-               isManual: onboardingMethod === onboardingMethodTypes.MANUAL,
-               version
-       };
+const mapStateToProps = ({
+    softwareProduct,
+    currentScreen: { props: { version } }
+}) => {
+    let {
+        softwareProductEditor: { data: currentSoftwareProduct = {} },
+        softwareProductComponents
+    } = softwareProduct;
+    let { componentsList } = softwareProductComponents;
+    let {
+        onboardingMethod = onboardingMethodTypes.HEAT
+    } = currentSoftwareProduct;
+    return {
+        currentSoftwareProduct,
+        componentsList,
+        isManual: onboardingMethod === onboardingMethodTypes.MANUAL,
+        version
+    };
 };
 
-const mapActionToProps = (dispatch) => {
-       return {
-               onComponentSelect: ({id: softwareProductId, componentId, version}) =>
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, screenType: screenTypes.SOFTWARE_PRODUCT,
-                               props: {softwareProductId, version, componentId}
-                       }),
-               onAddComponent: (softwareProductId, version) => SoftwareProductActionHelper.addComponent(dispatch, {softwareProductId, version, modalClassName: 'create-vfc-modal'}),
-               onDeleteComponent: (component, softwareProductId, version) => dispatch({
-                       type: ConfirmationModalConstants.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: generateMessage(component.displayName),
-                               onConfirmed: ()=>SoftwareProductComponentsActionHelper.deleteComponent(dispatch, {
-                                       softwareProductId,
-                                       componentId: component.id,
-                                       version
-                               })
-                       }
-               })
-       };
+const mapActionToProps = dispatch => {
+    return {
+        onComponentSelect: ({ id: softwareProductId, componentId, version }) =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: { softwareProductId, version, componentId }
+            }),
+        onAddComponent: (softwareProductId, version) =>
+            SoftwareProductActionHelper.addComponent(dispatch, {
+                softwareProductId,
+                version,
+                modalClassName: 'create-vfc-modal'
+            }),
+        onDeleteComponent: (component, softwareProductId, version) =>
+            dispatch({
+                type: ConfirmationModalConstants.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: generateMessage(component.displayName),
+                    onConfirmed: () =>
+                        SoftwareProductComponentsActionHelper.deleteComponent(
+                            dispatch,
+                            {
+                                softwareProductId,
+                                componentId: component.id,
+                                version
+                            }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductComponentsView);
+export default connect(mapStateToProps, mapActionToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsView);
index cf63ad7..73a971c 100644 (file)
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 
-import {actionTypes, COMPONENTS_QUESTIONNAIRE} from './SoftwareProductComponentsConstants.js';
+import {
+    actionTypes,
+    COMPONENTS_QUESTIONNAIRE
+} from './SoftwareProductComponentsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 function baseUrl(softwareProductId, version) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components`;
 }
 
 function fetchSoftwareProductComponents(softwareProductId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
 }
 
-function putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, vspComponent) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`, vspComponent);
+function putSoftwareProductComponentQuestionnaire(
+    softwareProductId,
+    version,
+    vspComponentId,
+    vspComponent
+) {
+    return RestAPIUtil.put(
+        `${baseUrl(
+            softwareProductId,
+            version
+        )}/${vspComponentId}/questionnaire`,
+        vspComponent
+    );
 }
 
-function fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId){
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`);
+function fetchSoftwareProductComponentQuestionnaire(
+    softwareProductId,
+    version,
+    vspComponentId
+) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`
+    );
 }
 
-function fetchSoftwareProductComponent(softwareProductId, version, vspComponentId){
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}`);
+function fetchSoftwareProductComponent(
+    softwareProductId,
+    version,
+    vspComponentId
+) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version)}/${vspComponentId}`
+    );
 }
 
-function putSoftwareProductComponent(softwareProductId, version, vspComponentId, vspComponent) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}`, {
-               name: vspComponent.name,
-               displayName: vspComponent.displayName,
-               vfcCode: vspComponent.vfcCode,
-               nfcFunction: vspComponent.nfcFunction,
-               description: vspComponent.description
-       });
+function putSoftwareProductComponent(
+    softwareProductId,
+    version,
+    vspComponentId,
+    vspComponent
+) {
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version)}/${vspComponentId}`,
+        {
+            name: vspComponent.name,
+            displayName: vspComponent.displayName,
+            vfcCode: vspComponent.vfcCode,
+            nfcFunction: vspComponent.nfcFunction,
+            description: vspComponent.description
+        }
+    );
 }
 
-function deleteSoftwareProductComponent(softwareProductId, componentId, version) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${componentId}`,);
+function deleteSoftwareProductComponent(
+    softwareProductId,
+    componentId,
+    version
+) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version)}/${componentId}`
+    );
 }
 
+function postSoftwareProductComponent(
+    softwareProductId,
+    vspComponent,
+    version
+) {
+    return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
+        name: vspComponent.displayName,
+        displayName: vspComponent.displayName,
+        description: vspComponent.description
+    });
+}
 
-function postSoftwareProductComponent(softwareProductId, vspComponent, version) {
+const SoftwareProductComponentsActionHelper = {
+    fetchSoftwareProductComponents(dispatch, { softwareProductId, version }) {
+        return fetchSoftwareProductComponents(softwareProductId, version).then(
+            response => {
+                dispatch({
+                    type: actionTypes.COMPONENTS_LIST_UPDATE,
+                    componentsList: response.results
+                });
+                return response;
+            }
+        );
+    },
 
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
-               name: vspComponent.displayName,
-               displayName: vspComponent.displayName,
-               description: vspComponent.description
-       });
-}
+    updateSoftwareProductComponent(
+        dispatch,
+        { softwareProductId, version, vspComponentId, componentData, qdata }
+    ) {
+        return Promise.all([
+            SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                { softwareProductId, version, vspComponentId, qdata }
+            ),
+            SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData(
+                dispatch,
+                { softwareProductId, version, vspComponentId, componentData }
+            )
+        ]);
+    },
 
+    updateSoftwareProductComponentQuestionnaire(
+        dispatch,
+        { softwareProductId, version, vspComponentId, qdata }
+    ) {
+        return putSoftwareProductComponentQuestionnaire(
+            softwareProductId,
+            version,
+            vspComponentId,
+            qdata
+        );
+    },
 
-const SoftwareProductComponentsActionHelper = {
-       fetchSoftwareProductComponents(dispatch, {softwareProductId, version}) {
-               return fetchSoftwareProductComponents(softwareProductId, version).then(response => {
-                       dispatch({
-                               type: actionTypes.COMPONENTS_LIST_UPDATE,
-                               componentsList: response.results
-                       });
-                       return response;
-               });
-       },
-
-       updateSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId, componentData, qdata}) {
-               return Promise.all([
-                       SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}),
-                       SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData})
-               ]);
-       },
-
-       updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}) {
-               return putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, qdata);
-       },
-
-       updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData}) {
-               return putSoftwareProductComponent(softwareProductId, version, vspComponentId, componentData).then(() => dispatch({
-                       type: actionTypes.COMPONENTS_LIST_EDIT,
-                       component: {
-                               id: vspComponentId,
-                               ...componentData
-                       }
-               }));
-       },
-
-       fetchSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId}) {
-               return fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId).then(response => {
-                       ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_QUESTIONNAIRE, response: {qdata: response.data ? JSON.parse(response.data) : {},
-                               qschema: JSON.parse(response.schema)}});
-               });
-       },
-
-       fetchSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId}) {
-               return Promise.all([
-                       fetchSoftwareProductComponent(softwareProductId, version, vspComponentId).then(response => {
-                               dispatch({
-                                       type: actionTypes.COMPONENT_LOAD,
-                                       component: response.data
-                               });
-                               return response;
-                       }),
-                       fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId).then(response => {
-                               ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_QUESTIONNAIRE, response: {qdata: response.data ? JSON.parse(response.data) : {},
-                                       qschema: JSON.parse(response.schema)}});
-                       })
-               ]);
-       },
-
-
-       clearComponentsStore(dispatch) {
-               dispatch({
-                       type: actionTypes.COMPONENTS_LIST_UPDATE,
-                       componentsList: []
-               });
-       },
-
-       createSoftwareProductComponent(dispatch,{softwareProductId, componentData, version}) {
-               SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch);
-               /* for mock only */
-
-               dispatch({
-                       type: actionTypes.COMPONENTS_LIST_UPDATE,
-                       componentsList: [{id: '123', ...componentData}]
-               });
-
-               postSoftwareProductComponent(softwareProductId, componentData, version).then(() => {
-                       SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
-               });
-       },
-
-       clearComponentCreationData(dispatch) {
-               dispatch({
-                       type: actionTypes.COMPONENT_DATA_CLEAR
-               });
-       },
-
-       closeComponentCreationModal(dispatch) {
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-               SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch);
-       },
-
-       deleteComponent(dispatch, {softwareProductId, componentId, version}) {
-               deleteSoftwareProductComponent(softwareProductId, componentId, version);
-               dispatch({
-                       type: actionTypes.COMPONENT_DELETE,
-                       componentId: componentId
-               });
-       },
+    updateSoftwareProductComponentData(
+        dispatch,
+        { softwareProductId, version, vspComponentId, componentData }
+    ) {
+        return putSoftwareProductComponent(
+            softwareProductId,
+            version,
+            vspComponentId,
+            componentData
+        ).then(() =>
+            dispatch({
+                type: actionTypes.COMPONENTS_LIST_EDIT,
+                component: {
+                    id: vspComponentId,
+                    ...componentData
+                }
+            })
+        );
+    },
+
+    fetchSoftwareProductComponentQuestionnaire(
+        dispatch,
+        { softwareProductId, version, vspComponentId }
+    ) {
+        return fetchSoftwareProductComponentQuestionnaire(
+            softwareProductId,
+            version,
+            vspComponentId
+        ).then(response => {
+            ValidationHelper.qDataLoaded(dispatch, {
+                qName: COMPONENTS_QUESTIONNAIRE,
+                response: {
+                    qdata: response.data ? JSON.parse(response.data) : {},
+                    qschema: JSON.parse(response.schema)
+                }
+            });
+        });
+    },
+
+    fetchSoftwareProductComponent(
+        dispatch,
+        { softwareProductId, version, vspComponentId }
+    ) {
+        return Promise.all([
+            fetchSoftwareProductComponent(
+                softwareProductId,
+                version,
+                vspComponentId
+            ).then(response => {
+                dispatch({
+                    type: actionTypes.COMPONENT_LOAD,
+                    component: response.data
+                });
+                return response;
+            }),
+            fetchSoftwareProductComponentQuestionnaire(
+                softwareProductId,
+                version,
+                vspComponentId
+            ).then(response => {
+                ValidationHelper.qDataLoaded(dispatch, {
+                    qName: COMPONENTS_QUESTIONNAIRE,
+                    response: {
+                        qdata: response.data ? JSON.parse(response.data) : {},
+                        qschema: JSON.parse(response.schema)
+                    }
+                });
+            })
+        ]);
+    },
+
+    clearComponentsStore(dispatch) {
+        dispatch({
+            type: actionTypes.COMPONENTS_LIST_UPDATE,
+            componentsList: []
+        });
+    },
+
+    createSoftwareProductComponent(
+        dispatch,
+        { softwareProductId, componentData, version }
+    ) {
+        SoftwareProductComponentsActionHelper.closeComponentCreationModal(
+            dispatch
+        );
+        /* for mock only */
+
+        dispatch({
+            type: actionTypes.COMPONENTS_LIST_UPDATE,
+            componentsList: [{ id: '123', ...componentData }]
+        });
+
+        postSoftwareProductComponent(
+            softwareProductId,
+            componentData,
+            version
+        ).then(() => {
+            SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+                dispatch,
+                { softwareProductId, version }
+            );
+        });
+    },
 
+    clearComponentCreationData(dispatch) {
+        dispatch({
+            type: actionTypes.COMPONENT_DATA_CLEAR
+        });
+    },
 
+    closeComponentCreationModal(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+        SoftwareProductComponentsActionHelper.clearComponentCreationData(
+            dispatch
+        );
+    },
 
+    deleteComponent(dispatch, { softwareProductId, componentId, version }) {
+        deleteSoftwareProductComponent(softwareProductId, componentId, version);
+        dispatch({
+            type: actionTypes.COMPONENT_DELETE,
+            componentId: componentId
+        });
+    }
 };
 
 export default SoftwareProductComponentsActionHelper;
index 35633b6..cc120d3 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       COMPONENTS_LIST_UPDATE: null,
-       COMPONENTS_LIST_EDIT: null,
-       COMPONENT_UPDATE: null,
-       COMPONENT_DATA_CHANGED: null,
-       COMPONENT_DATA_CLEAR: null,
-       COMPONENT_QUESTIONNAIRE_UPDATE: null,
-       COMPONENT_DELETE: null,
-       COMPONENT_LOAD: null,
-       COMPONENT_CREATE_OPEN: null
+    COMPONENTS_LIST_UPDATE: null,
+    COMPONENTS_LIST_EDIT: null,
+    COMPONENT_UPDATE: null,
+    COMPONENT_DATA_CHANGED: null,
+    COMPONENT_DATA_CLEAR: null,
+    COMPONENT_QUESTIONNAIRE_UPDATE: null,
+    COMPONENT_DELETE: null,
+    COMPONENT_LOAD: null,
+    COMPONENT_CREATE_OPEN: null
 });
 
-export const storageConstants  = keyMirror({
-       backupType: {
-               ON_SITE: 'OnSite',
-               OFF_SITE: 'OffSite'
-       }
+export const storageConstants = keyMirror({
+    backupType: {
+        ON_SITE: 'OnSite',
+        OFF_SITE: 'OffSite'
+    }
 });
 
 export const forms = keyMirror({
-       ALL_SPC_FORMS: null,
-       NIC_EDIT_FORM: null,
-       CREATE_FORM: null,
-       IMAGE_EDIT_FORM: null
+    ALL_SPC_FORMS: null,
+    NIC_EDIT_FORM: null,
+    CREATE_FORM: null,
+    IMAGE_EDIT_FORM: null
 });
 
 export const COMPONENTS_QUESTIONNAIRE = 'component';
 export const COMPONENTS_COMPUTE_QUESTIONNAIRE = 'compute';
 
 export const navigationItems = keyMirror({
-       STORAGE: 'Storage',
-       PROCESS_DETAILS: 'Process Details',
-       MONITORING: 'Monitoring',
-       NETWORK: 'Network',
-       IMAGES: 'Images',
-       COMPUTE: 'Compute',
-       LOAD_BALANCING: 'High Availability & Load Balancing'
+    STORAGE: 'Storage',
+    PROCESS_DETAILS: 'Process Details',
+    MONITORING: 'Monitoring',
+    NETWORK: 'Network',
+    IMAGES: 'Images',
+    COMPUTE: 'Compute',
+    LOAD_BALANCING: 'High Availability & Load Balancing'
 });
index 92211e0..e1cf5f4 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentsConstants.js';
+import { actionTypes } from './SoftwareProductComponentsConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.COMPONENTS_LIST_UPDATE:
-                       return [...action.componentsList];
-               case actionTypes.COMPONENTS_LIST_EDIT:
-                       const indexForEdit = state.findIndex(component => component.id === action.component.id);
-                       return [...state.slice(0, indexForEdit), action.component, ...state.slice(indexForEdit + 1)];
-               case actionTypes.COMPONENT_DELETE:
-                       return state.filter(component => component.id !== action.componentId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.COMPONENTS_LIST_UPDATE:
+            return [...action.componentsList];
+        case actionTypes.COMPONENTS_LIST_EDIT:
+            const indexForEdit = state.findIndex(
+                component => component.id === action.component.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.component,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.COMPONENT_DELETE:
+            return state.filter(
+                component => component.id !== action.componentId
+            );
+        default:
+            return state;
+    }
 };
index 0bf32df..fc8abf6 100644 (file)
@@ -22,85 +22,113 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
 
 const ComponentPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       displayName: PropTypes.string,
-       description: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    displayName: PropTypes.string,
+    description: PropTypes.string
 });
 
 class SoftwareProductComponentsListView extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
+    static propTypes = {
+        isReadOnlyMode: PropTypes.bool,
+        componentsList: PropTypes.arrayOf(ComponentPropType),
+        onComponentSelect: PropTypes.func
+    };
 
-       static propTypes = {
-               isReadOnlyMode: PropTypes.bool,
-               componentsList: PropTypes.arrayOf(ComponentPropType),
-               onComponentSelect: PropTypes.func
-       };
+    render() {
+        let { componentsList = [], isManual } = this.props;
+        return (
+            <div className="">
+                {(componentsList.length > 0 || isManual) &&
+                    this.renderComponents()}
+            </div>
+        );
+    }
 
-       render() {
-               let {componentsList = [], isManual} =  this.props;
-               return (
-                       <div className=''>
-                               {
-                                       (componentsList.length > 0 || isManual) && this.renderComponents()
-                               }
-                       </div>
-               );
-       }
+    renderComponents() {
+        const { localFilter } = this.state;
+        const {
+            isManual,
+            onAddComponent,
+            isReadOnlyMode,
+            version,
+            currentSoftwareProduct: { id: softwareProductId },
+            componentsList
+        } = this.props;
+        return (
+            <ListEditorView
+                title={i18n('Virtual Function Components')}
+                filterValue={localFilter}
+                placeholder={i18n('Filter Components')}
+                onFilter={value => this.setState({ localFilter: value })}
+                isReadOnlyMode={isReadOnlyMode || !!this.filterList().length}
+                plusButtonTitle={i18n('Add Component')}
+                onAdd={
+                    isManual && componentsList.length === 0
+                        ? () => onAddComponent(softwareProductId, version)
+                        : false
+                }
+                twoColumns>
+                {this.filterList().map(component =>
+                    this.renderComponentsListItem(component)
+                )}
+            </ListEditorView>
+        );
+    }
 
-       renderComponents() {
-               const {localFilter} = this.state;
-               const {isManual, onAddComponent, isReadOnlyMode, version, currentSoftwareProduct: {id: softwareProductId}, componentsList } = this.props;
-               return (
-                       <ListEditorView
-                               title={i18n('Virtual Function Components')}
-                               filterValue={localFilter}
-                               placeholder={i18n('Filter Components')}
-                               onFilter={value => this.setState({localFilter: value})}
-                               isReadOnlyMode={isReadOnlyMode || !!this.filterList().length}
-                               plusButtonTitle={i18n('Add Component')}
-                               onAdd={isManual && componentsList.length === 0 ? () => onAddComponent(softwareProductId, version) : false}
-                               twoColumns>
-                               {this.filterList().map(component => this.renderComponentsListItem(component))}
-                       </ListEditorView>
-               );
-       }
+    renderComponentsListItem(component) {
+        let {
+            id: componentId,
+            name,
+            displayName,
+            description = ''
+        } = component;
+        let {
+            currentSoftwareProduct: { id },
+            onComponentSelect,
+            version
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={
+                    name + Math.floor(Math.random() * (100 - 1) + 1).toString()
+                }
+                className="list-editor-item-view"
+                onSelect={() =>
+                    onComponentSelect({ id, componentId, version })
+                }>
+                <ListEditorItemViewField>
+                    <div className="name">{displayName}</div>
+                </ListEditorItemViewField>
+                <ListEditorItemViewField>
+                    <div className="description">{description}</div>
+                </ListEditorItemViewField>
+            </ListEditorItemView>
+        );
+    }
 
-       renderComponentsListItem(component) {
-               let {id: componentId, name, displayName, description = ''} = component;
-               let {currentSoftwareProduct: {id}, onComponentSelect, version} = this.props;
-               return (
-                       <ListEditorItemView
-                               key={name + Math.floor(Math.random() * (100 - 1) + 1).toString()}
-                               className='list-editor-item-view'                               
-                               onSelect={() => onComponentSelect({id, componentId, version})}>
-                               <ListEditorItemViewField>
-                                       <div className='name'>{displayName}</div>
-                               </ListEditorItemViewField>
-                               <ListEditorItemViewField>
-                                       <div className='description'>{description}</div>
-                               </ListEditorItemViewField>
-                       </ListEditorItemView>
-               );
-       }
+    filterList() {
+        let { componentsList = [] } = this.props;
 
-       filterList() {
-               let {componentsList = []} = this.props;
-
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return componentsList.filter(({displayName = '', description = ''}) => {
-                               return escape(displayName).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return componentsList;
-               }
-       }
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return componentsList.filter(
+                ({ displayName = '', description = '' }) => {
+                    return (
+                        escape(displayName).match(filter) ||
+                        escape(description).match(filter)
+                    );
+                }
+            );
+        } else {
+            return componentsList;
+        }
+    }
 }
 
 export default SoftwareProductComponentsListView;
index 02c09fb..cd37c31 100644 (file)
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes} from './computeComponents/computeFlavor/ComputeFlavorConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes as globalModalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes } from './computeComponents/computeFlavor/ComputeFlavorConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import {
+    actionTypes as globalModalActionTypes,
+    modalSizes
+} from 'nfvo-components/modal/GlobalModalConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { COMPONENTS_COMPUTE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 
 function baseUrl(softwareProductId, componentId, version) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/compute-flavors`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/compute-flavors`;
 }
 
-function baseUrlVSPLevel(softwareProductId, version){
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/compute-flavors`;
+function baseUrlVSPLevel(softwareProductId, version) {
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/compute-flavors`;
 }
 
-function fetchComputesList(softwareProductId, componentId, version){
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}`);
+function fetchComputesList(softwareProductId, componentId, version) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, componentId, version)}`
+    );
 }
 
-function fetchComputesListForVSP(softwareProductId, version){
-       return RestAPIUtil.fetch(`${baseUrlVSPLevel(softwareProductId, version)}`);
+function fetchComputesListForVSP(softwareProductId, version) {
+    return RestAPIUtil.fetch(`${baseUrlVSPLevel(softwareProductId, version)}`);
 }
 
 function fetchCompute(softwareProductId, componentId, computeId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, componentId, version)}/${computeId}`
+    );
 }
 
-function fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`);
+function fetchComputeQuestionnaire({
+    softwareProductId,
+    componentId,
+    computeId,
+    version
+}) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(
+            softwareProductId,
+            componentId,
+            version
+        )}/${computeId}/questionnaire`
+    );
 }
 
-function postCompute({softwareProductId, componentId, compute, version}) {
-       return RestAPIUtil.post(baseUrl(softwareProductId, componentId, version), compute);
+function postCompute({ softwareProductId, componentId, compute, version }) {
+    return RestAPIUtil.post(
+        baseUrl(softwareProductId, componentId, version),
+        compute
+    );
 }
 
-function putCompute({softwareProductId, componentId, compute, version}) {
-       const computeData = {
-               name: compute.name,
-               description: compute.description
-       };
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${compute.id}`, computeData);
+function putCompute({ softwareProductId, componentId, compute, version }) {
+    const computeData = {
+        name: compute.name,
+        description: compute.description
+    };
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, componentId, version)}/${compute.id}`,
+        computeData
+    );
 }
 
-function putComputeQuestionnaire({softwareProductId, componentId, computeId, qdata, version}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`, qdata);
+function putComputeQuestionnaire({
+    softwareProductId,
+    componentId,
+    computeId,
+    qdata,
+    version
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(
+            softwareProductId,
+            componentId,
+            version
+        )}/${computeId}/questionnaire`,
+        qdata
+    );
 }
 
-function deleteCompute({softwareProductId, componentId, computeId, version}) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`);
+function deleteCompute({ softwareProductId, componentId, computeId, version }) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, componentId, version)}/${computeId}`
+    );
 }
 
-
 const ComputeFlavorActionHelper = {
-       openComputeEditor(dispatch, {props}) {
-               dispatch({
-                       type: actionTypes.computeEditor.LOAD_EDITOR_DATA,
-                       compute: props.compute || {}
-               });
-               dispatch({
-                       type: globalModalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.COMPONENT_COMPUTE_FLAVOR_EDITOR,
-                               modalClassName: `compute-flavor-editor-modal-${props.compute ? 'edit' : 'create'}`,
-                               modalComponentProps: {...props, size: props.compute ? modalSizes.LARGE : undefined, dialogClassName:'compute-flavor-editor-modal'},
-                               title: `${props.compute ? i18n('Edit Compute Flavor') : i18n('Create New Compute Flavor')}`
-                       }
-               });
-       },
-
-       closeComputeEditor(dispatch){
-               dispatch({
-                       type: globalModalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-               dispatch({
-                       type: actionTypes.computeEditor.CLEAR_DATA
-               });
-       },
-
-       fetchComputesList(dispatch, {softwareProductId, componentId, version}) {
-               return fetchComputesList(softwareProductId, componentId, version).then(response => dispatch({
-                       type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
-                       response
-               }));
-       },
-
-       fetchComputesListForVSP(dispatch, {softwareProductId, version}) {
-               return fetchComputesListForVSP(softwareProductId, version).then(response => dispatch({
-                       type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
-                       response
-               }));
-       },
-
-       loadComputeData({softwareProductId, componentId, computeId, version}) {
-               return fetchCompute(softwareProductId, componentId, computeId, version);
-       },
-
-       loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}) {
-               return fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}).then(response =>
-                       ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_COMPUTE_QUESTIONNAIRE ,response: {
-                               qdata: response.data ? JSON.parse(response.data) : {},
-                               qschema: JSON.parse(response.schema)
-                       }})
-               );
-       },
-
-       loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}){
-               return ComputeFlavorActionHelper.loadComputeData({softwareProductId, componentId, computeId, version}).then(({data}) =>
-                       ComputeFlavorActionHelper.loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}).then(() =>
-                               ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, version, isReadOnlyMode, compute: {id: computeId, ...data}}})
-                       ));
-       },
-
-       saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data: compute, qdata, version}) {
-               ComputeFlavorActionHelper.closeComputeEditor(dispatch);
-               if(compute.id) {
-                       return Promise.all([
-                               putComputeQuestionnaire({softwareProductId, componentId, computeId: compute.id, qdata, version}),
-                               putCompute({softwareProductId, componentId, compute, version}).then(() => {
-                                       dispatch({
-                                               type: actionTypes.COMPUTE_LIST_EDIT,
-                                               compute
-                                       });
-                               })
-                       ]);
-               }
-               else {
-                       return postCompute({softwareProductId, componentId, compute, version}).then(response =>
-                               dispatch({
-                                       type: actionTypes.ADD_COMPUTE,
-                                       compute: {
-                                               ...compute,
-                                               id: response.id,
-                                               componentId
-                                       }
-                               })
-                       );
-               }
-       },
-
-       deleteCompute(dispatch, {softwareProductId, componentId, computeId, version}) {
-               return deleteCompute({softwareProductId, componentId, computeId, version}).then(() => dispatch({
-                       type: actionTypes.DELETE_COMPUTE,
-                       computeId
-               }));
-       }
+    openComputeEditor(dispatch, { props }) {
+        dispatch({
+            type: actionTypes.computeEditor.LOAD_EDITOR_DATA,
+            compute: props.compute || {}
+        });
+        dispatch({
+            type: globalModalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName:
+                    modalContentMapper.COMPONENT_COMPUTE_FLAVOR_EDITOR,
+                modalClassName: `compute-flavor-editor-modal-${
+                    props.compute ? 'edit' : 'create'
+                }`,
+                modalComponentProps: {
+                    ...props,
+                    size: props.compute ? modalSizes.LARGE : undefined,
+                    dialogClassName: 'compute-flavor-editor-modal'
+                },
+                title: `${
+                    props.compute
+                        ? i18n('Edit Compute Flavor')
+                        : i18n('Create New Compute Flavor')
+                }`
+            }
+        });
+    },
+
+    closeComputeEditor(dispatch) {
+        dispatch({
+            type: globalModalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+        dispatch({
+            type: actionTypes.computeEditor.CLEAR_DATA
+        });
+    },
+
+    fetchComputesList(dispatch, { softwareProductId, componentId, version }) {
+        return fetchComputesList(softwareProductId, componentId, version).then(
+            response =>
+                dispatch({
+                    type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
+                    response
+                })
+        );
+    },
+
+    fetchComputesListForVSP(dispatch, { softwareProductId, version }) {
+        return fetchComputesListForVSP(softwareProductId, version).then(
+            response =>
+                dispatch({
+                    type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
+                    response
+                })
+        );
+    },
+
+    loadComputeData({ softwareProductId, componentId, computeId, version }) {
+        return fetchCompute(softwareProductId, componentId, computeId, version);
+    },
+
+    loadComputeQuestionnaire(
+        dispatch,
+        { softwareProductId, componentId, computeId, version }
+    ) {
+        return fetchComputeQuestionnaire({
+            softwareProductId,
+            componentId,
+            computeId,
+            version
+        }).then(response =>
+            ValidationHelper.qDataLoaded(dispatch, {
+                qName: COMPONENTS_COMPUTE_QUESTIONNAIRE,
+                response: {
+                    qdata: response.data ? JSON.parse(response.data) : {},
+                    qschema: JSON.parse(response.schema)
+                }
+            })
+        );
+    },
+
+    loadCompute(
+        dispatch,
+        { softwareProductId, componentId, version, computeId, isReadOnlyMode }
+    ) {
+        return ComputeFlavorActionHelper.loadComputeData({
+            softwareProductId,
+            componentId,
+            computeId,
+            version
+        }).then(({ data }) =>
+            ComputeFlavorActionHelper.loadComputeQuestionnaire(dispatch, {
+                softwareProductId,
+                componentId,
+                computeId,
+                version
+            }).then(() =>
+                ComputeFlavorActionHelper.openComputeEditor(dispatch, {
+                    props: {
+                        softwareProductId,
+                        componentId,
+                        version,
+                        isReadOnlyMode,
+                        compute: { id: computeId, ...data }
+                    }
+                })
+            )
+        );
+    },
+
+    saveComputeDataAndQuestionnaire(
+        dispatch,
+        { softwareProductId, componentId, data: compute, qdata, version }
+    ) {
+        ComputeFlavorActionHelper.closeComputeEditor(dispatch);
+        if (compute.id) {
+            return Promise.all([
+                putComputeQuestionnaire({
+                    softwareProductId,
+                    componentId,
+                    computeId: compute.id,
+                    qdata,
+                    version
+                }),
+                putCompute({
+                    softwareProductId,
+                    componentId,
+                    compute,
+                    version
+                }).then(() => {
+                    dispatch({
+                        type: actionTypes.COMPUTE_LIST_EDIT,
+                        compute
+                    });
+                })
+            ]);
+        } else {
+            return postCompute({
+                softwareProductId,
+                componentId,
+                compute,
+                version
+            }).then(response =>
+                dispatch({
+                    type: actionTypes.ADD_COMPUTE,
+                    compute: {
+                        ...compute,
+                        id: response.id,
+                        componentId
+                    }
+                })
+            );
+        }
+    },
+
+    deleteCompute(
+        dispatch,
+        { softwareProductId, componentId, computeId, version }
+    ) {
+        return deleteCompute({
+            softwareProductId,
+            componentId,
+            computeId,
+            version
+        }).then(() =>
+            dispatch({
+                type: actionTypes.DELETE_COMPUTE,
+                computeId
+            })
+        );
+    }
 };
 
 export default ComputeFlavorActionHelper;
index 574828c..d595a82 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentComputeView from './SoftwareProductComponentComputeView.jsx';
 import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js';
-import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { onboardingMethod } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
+const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: { data: currentVSP },
+        softwareProductComponents
+    } = softwareProduct;
+    let {
+        componentEditor: { qdata, dataMap, qgenericFieldInfo },
+        computeFlavor: { computesList: computeFlavorsList }
+    } = softwareProductComponents;
 
-const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
-       let {componentEditor: {qdata, dataMap, qgenericFieldInfo}, computeFlavor: {computesList: computeFlavorsList}} = softwareProductComponents;
-
-       return {
-               qdata,
-               dataMap,
-               qgenericFieldInfo,
-               computeFlavorsList,
-               isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL
-       };
+    return {
+        qdata,
+        dataMap,
+        qgenericFieldInfo,
+        computeFlavorsList,
+        isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL
+    };
 };
 
-const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => {
-       return {
-               onQDataChanged: (deltaData, customValidations) => ValidationHelper.qDataChanged(dispatch, {deltaData, customValidations: customValidations,
-                       qName: COMPONENTS_QUESTIONNAIRE}),
-               onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});},
-               qValidateData: (data, customValidations) => ValidationHelper.qValidateData(dispatch, {data, customValidations: customValidations,
-                       qName: COMPONENTS_QUESTIONNAIRE})
-       };
+const mapActionToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onQDataChanged: (deltaData, customValidations) =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                customValidations: customValidations,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onSubmit: ({ qdata }) => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    vspComponentId: componentId,
+                    qdata
+                }
+            );
+        },
+        qValidateData: (data, customValidations) =>
+            ValidationHelper.qValidateData(dispatch, {
+                data,
+                customValidations: customValidations,
+                qName: COMPONENTS_QUESTIONNAIRE
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true}) (SoftwareProductComponentComputeView);
+export default connect(mapStateToProps, mapActionToProps, null, {
+    withRef: true
+})(SoftwareProductComponentComputeView);
index 55e5e2b..e6ce966 100644 (file)
@@ -22,67 +22,99 @@ import ComputeFlavors from './computeComponents/ComputeFlavors.js';
 import Validator from 'nfvo-utils/Validator.js';
 
 class SoftwareProductComponentComputeView extends React.Component {
+    static propTypes = {
+        dataMap: PropTypes.object,
+        qgenericFieldInfo: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        isManual: PropTypes.bool,
+        onQDataChanged: PropTypes.func.isRequired,
+        qValidateData: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               dataMap: PropTypes.object,
-               qgenericFieldInfo: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               isManual: PropTypes.bool,
-               onQDataChanged: PropTypes.func.isRequired,
-               qValidateData: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired
-       };
+    render() {
+        let {
+            softwareProductId,
+            componentId,
+            version,
+            qdata,
+            dataMap,
+            qgenericFieldInfo,
+            isReadOnlyMode,
+            onQDataChanged,
+            qValidateData,
+            onSubmit,
+            computeFlavorsList,
+            isManual
+        } = this.props;
 
-       render() {
-               let {softwareProductId, componentId, version, qdata, dataMap, qgenericFieldInfo, isReadOnlyMode, onQDataChanged, qValidateData,
-                       onSubmit, computeFlavorsList, isManual} = this.props;
+        return (
+            <div className="vsp-component-questionnaire-view">
+                {qgenericFieldInfo && (
+                    <Form
+                        ref={form => {
+                            this.form = form;
+                        }}
+                        formReady={null}
+                        isValid={true}
+                        hasButtons={false}
+                        onSubmit={() => onSubmit({ qdata })}
+                        className="component-questionnaire-validation-form"
+                        isReadOnlyMode={isReadOnlyMode}>
+                        <NumberOfVms
+                            onQDataChanged={onQDataChanged}
+                            dataMap={dataMap}
+                            qgenericFieldInfo={qgenericFieldInfo}
+                            qValidateData={qValidateData}
+                            customValidations={{
+                                'compute/numOfVMs/maximum': this.validateMax,
+                                'compute/numOfVMs/minimum': this.validateMin
+                            }}
+                        />
+                        <GuestOs
+                            onQDataChanged={onQDataChanged}
+                            dataMap={dataMap}
+                            qgenericFieldInfo={qgenericFieldInfo}
+                        />
+                        <ComputeFlavors
+                            computeFlavorsList={computeFlavorsList}
+                            softwareProductId={softwareProductId}
+                            componentId={componentId}
+                            version={version}
+                            isReadOnlyMode={isReadOnlyMode}
+                            isManual={isManual}
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-               return (
-                       <div className='vsp-component-questionnaire-view'>
-                               { qgenericFieldInfo && <Form
-                                       ref={ (form) => { this.form = form; }}
-                                       formReady={null}
-                                       isValid={true}
-                                       hasButtons={false}
-                                       onSubmit={() => onSubmit({qdata})}
-                                       className='component-questionnaire-validation-form'
-                                       isReadOnlyMode={isReadOnlyMode} >
-                                       <NumberOfVms onQDataChanged={onQDataChanged} dataMap={dataMap}
-                                                qgenericFieldInfo={qgenericFieldInfo} qValidateData={qValidateData}
-                                                customValidations={{'compute/numOfVMs/maximum' : this.validateMax, 'compute/numOfVMs/minimum': this.validateMin}} />
-                                       <GuestOs onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} />
-                                       <ComputeFlavors computeFlavorsList={computeFlavorsList} softwareProductId={softwareProductId} componentId={componentId}
-                                               version={version} isReadOnlyMode={isReadOnlyMode} isManual={isManual}/>
-                               </Form> }
-                       </div>
-               );
-       }
+    save() {
+        return this.form.handleFormSubmit(new Event('dummy'));
+    }
 
-       save(){
-               return this.form.handleFormSubmit(new Event('dummy'));
-       }
+    validateMin(value, state) {
+        let maxVal = state.dataMap['compute/numOfVMs/maximum'];
+        // we are allowed to have an empty maxval, that will allow all minvals.
+        // if we do not have a minval than there is no point to check it either.
+        if (value === undefined || maxVal === undefined) {
+            return { isValid: true, errorText: '' };
+        } else {
+            return Validator.validateItem(value, maxVal, 'maximum');
+        }
+    }
 
-       validateMin(value, state) {
-               let maxVal = state.dataMap['compute/numOfVMs/maximum'];
-               // we are allowed to have an empty maxval, that will allow all minvals.
-               // if we do not have a minval than there is no point to check it either.
-               if (value === undefined || maxVal === undefined) {
-                       return { isValid: true, errorText: '' };
-               } else {
-                       return Validator.validateItem(value, maxVal,'maximum');
-               }
-       }
-
-       validateMax(value, state) {
-               let minVal = state.dataMap['compute/numOfVMs/minimum'];
-               if (minVal === undefined ) {
-                       // having no minimum is the same as 0, maximum value doesn't need to be checked
-                       // against it.
-                       return { isValid: true, errorText: '' };
-               } else {
-                       return Validator.validateItem(value,minVal,'minimum');
-               }
-       }
+    validateMax(value, state) {
+        let minVal = state.dataMap['compute/numOfVMs/minimum'];
+        if (minVal === undefined) {
+            // having no minimum is the same as 0, maximum value doesn't need to be checked
+            // against it.
+            return { isValid: true, errorText: '' };
+        } else {
+            return Validator.validateItem(value, minVal, 'minimum');
+        }
+    }
 }
 
 export default SoftwareProductComponentComputeView;
index 2b6d84f..2004c94 100644 (file)
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onAddComputeClick: (isReadOnlyMode) => ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, isReadOnlyMode, version}}),
-               onEditCompute: ({computeId, isReadOnlyMode}) => ComputeFlavorActionHelper.loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}),
-               onDeleteCompute: ({id, name}) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{name}"?', {name: name}),
-                               onConfirmed: () => ComputeFlavorActionHelper.deleteCompute(dispatch, {softwareProductId, componentId, computeId: id, version})
-                       }
-               })
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onAddComputeClick: isReadOnlyMode =>
+            ComputeFlavorActionHelper.openComputeEditor(dispatch, {
+                props: {
+                    softwareProductId,
+                    componentId,
+                    isReadOnlyMode,
+                    version
+                }
+            }),
+        onEditCompute: ({ computeId, isReadOnlyMode }) =>
+            ComputeFlavorActionHelper.loadCompute(dispatch, {
+                softwareProductId,
+                componentId,
+                version,
+                computeId,
+                isReadOnlyMode
+            }),
+        onDeleteCompute: ({ id, name }) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{name}"?', {
+                        name: name
+                    }),
+                    onConfirmed: () =>
+                        ComputeFlavorActionHelper.deleteCompute(dispatch, {
+                            softwareProductId,
+                            componentId,
+                            computeId: id,
+                            version
+                        })
+                }
+            })
+    };
 };
 
 const computeItemPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string
 });
 
 class ComputeFlavors extends React.Component {
+    static propTypes = {
+        isReadOnlyMode: PropTypes.bool,
+        isManual: PropTypes.bool,
+        onAddComputeClick: PropTypes.func,
+        computeFlavorsList: PropTypes.arrayOf(computeItemPropType)
+    };
 
-       static propTypes = {
-               isReadOnlyMode: PropTypes.bool,
-               isManual: PropTypes.bool,
-               onAddComputeClick: PropTypes.func,
-               computeFlavorsList: PropTypes.arrayOf(computeItemPropType)
-       };
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
+    render() {
+        const { localFilter } = this.state;
+        const {
+            isReadOnlyMode,
+            isManual,
+            onAddComputeClick,
+            onEditCompute,
+            onDeleteCompute
+        } = this.props;
+        return (
+            <div className="computes-list">
+                <ListEditorView
+                    title={i18n('Computes')}
+                    plusButtonTitle={i18n('Add Compute')}
+                    onAdd={
+                        isManual
+                            ? () => onAddComputeClick(isReadOnlyMode)
+                            : null
+                    }
+                    isReadOnlyMode={isReadOnlyMode}
+                    onFilter={
+                        isManual
+                            ? value => this.setState({ localFilter: value })
+                            : null
+                    }
+                    filterValue={localFilter}
+                    twoColumns>
+                    {this.filterList().map(computeItem => (
+                        <ComputeItem
+                            key={computeItem.id}
+                            computeItem={computeItem}
+                            isReadOnlyMode={isReadOnlyMode}
+                            isManual={isManual}
+                            onEditCompute={onEditCompute}
+                            onDeleteCompute={onDeleteCompute}
+                        />
+                    ))}
+                </ListEditorView>
+            </div>
+        );
+    }
 
-       render() {
-               const {localFilter} = this.state;
-               const {isReadOnlyMode, isManual, onAddComputeClick, onEditCompute, onDeleteCompute} = this.props;
-               return (
-                       <div className='computes-list'>
-                               <ListEditorView
-                                       title={i18n('Computes')}
-                                       plusButtonTitle={i18n('Add Compute')}
-                                       onAdd={isManual ? () => onAddComputeClick(isReadOnlyMode) : null}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       onFilter={isManual ? value => this.setState({localFilter: value}) : null}
-                                       filterValue={localFilter}
-                                       twoColumns>
-                                       {this.filterList().map(computeItem =>
-                                               <ComputeItem key={computeItem.id}
-                                                       computeItem={computeItem} isReadOnlyMode={isReadOnlyMode} isManual={isManual}
-                                                       onEditCompute={onEditCompute} onDeleteCompute={onDeleteCompute}/>)
-                                       }
-                               </ListEditorView>
-                       </div>
-               );
-       }
+    filterList() {
+        const { computeFlavorsList = [] } = this.props;
 
-       filterList() {
-               const {computeFlavorsList = []} = this.props;
-
-               const {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return computeFlavorsList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return computeFlavorsList;
-               }
-       }
+        const { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return computeFlavorsList.filter(
+                ({ name = '', description = '' }) => {
+                    return (
+                        escape(name).match(filter) ||
+                        escape(description).match(filter)
+                    );
+                }
+            );
+        } else {
+            return computeFlavorsList;
+        }
+    }
 }
 
-const ComputeItem = ({computeItem, isReadOnlyMode, isManual, onEditCompute, onDeleteCompute}) => {
-       const {id, name, description} = computeItem;
-       return (
-               <ListEditorItemView
-                       key={'item_' + id}
-                       className='list-editor-item-view'
-                       isReadOnlyMode={isReadOnlyMode}
-                       onSelect={() => onEditCompute({computeId: id, isReadOnlyMode})}
-                       onDelete={isManual ? () => onDeleteCompute({id, name}) : null}>
-
-                       <div className='list-editor-item-view-field'>
-                               <div className='name'>{name}</div>
-                       </div>
-                       <div className='list-editor-item-view-field'>
-                               <div className='description'>{description}</div>
-                       </div>
-               </ListEditorItemView>
-       );
+const ComputeItem = ({
+    computeItem,
+    isReadOnlyMode,
+    isManual,
+    onEditCompute,
+    onDeleteCompute
+}) => {
+    const { id, name, description } = computeItem;
+    return (
+        <ListEditorItemView
+            key={'item_' + id}
+            className="list-editor-item-view"
+            isReadOnlyMode={isReadOnlyMode}
+            onSelect={() => onEditCompute({ computeId: id, isReadOnlyMode })}
+            onDelete={isManual ? () => onDeleteCompute({ id, name }) : null}>
+            <div className="list-editor-item-view-field">
+                <div className="name">{name}</div>
+            </div>
+            <div className="list-editor-item-view-field">
+                <div className="description">{description}</div>
+            </div>
+        </ListEditorItemView>
+    );
 };
 
-export default connect(null, mapActionsToProps, null, {withRef: true})(ComputeFlavors);
+export default connect(null, mapActionsToProps, null, { withRef: true })(
+    ComputeFlavors
+);
index 8ae9961..c16ab5c 100644 (file)
@@ -19,57 +19,91 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-
-const GuestOs = ({qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return(
-               <div>
-                       <GridSection title={i18n('Guest OS')} hasLastColSet>
-                               <GridItem>
-                                       <div className='vertical-flex'>
-                                               <label key='label' className='control-label'>{i18n('OS Bit Size')}</label>
-                                               <div className='radio-options-content-row'>
-                                                       {qgenericFieldInfo['compute/guestOS/bitSize'].enum.map(bitSize => (
-                                                       <Input
-                                                               data-test-id='guestOS-bitSize'
-                                                               type='radio'
-                                                               key={bitSize.enum}
-                                                               name={'compute/guestOS/bitSize'}
-                                                               className='radio-field'
-                                                               value={bitSize.enum}
-                                                               label={bitSize.title}
-                                                               onChange={(bit) => onQDataChanged({'compute/guestOS/bitSize' :  Number(bit)})}
-                                                               isValid={qgenericFieldInfo['compute/guestOS/bitSize'].isValid}
-                                                               errorText={qgenericFieldInfo['compute/guestOS/bitSize'].errorText}
-                                                               checked={dataMap['compute/guestOS/bitSize'] === bitSize.enum} /> )) }
-                                               </div>
-                                       </div>
-                               </GridItem>
-                               <GridItem colSpan={2}/>
-                               <GridItem colSpan={2}>
-                                       <Input
-                                               data-test-id='guestOS-name'
-                                               label={i18n('Guest OS')}
-                                               type='textarea'
-                                               onChange={(tools) => onQDataChanged({'compute/guestOS/name' : tools})}
-                                               isValid={qgenericFieldInfo['compute/guestOS/name'].isValid}
-                                               errorText={qgenericFieldInfo['compute/guestOS/name'].errorText}
-                                               value={dataMap['compute/guestOS/name']} />
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow>
-                                       <Input
-                                               data-test-id='guestOS-tools'
-                                               type='textarea'
-                                               label={i18n('Guest OS Tools:')}
-                                               onChange={(tools) => onQDataChanged({'compute/guestOS/tools' : tools})}
-                                               isValid={qgenericFieldInfo['compute/guestOS/tools'].isValid}
-                                               errorText={qgenericFieldInfo['compute/guestOS/tools'].errorText}
-                                               value={dataMap['compute/guestOS/tools']} />
-                               </GridItem>
-                       </GridSection>
-
-
-               </div>
-       );
+const GuestOs = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => {
+    return (
+        <div>
+            <GridSection title={i18n('Guest OS')} hasLastColSet>
+                <GridItem>
+                    <div className="vertical-flex">
+                        <label key="label" className="control-label">
+                            {i18n('OS Bit Size')}
+                        </label>
+                        <div className="radio-options-content-row">
+                            {qgenericFieldInfo[
+                                'compute/guestOS/bitSize'
+                            ].enum.map(bitSize => (
+                                <Input
+                                    data-test-id="guestOS-bitSize"
+                                    type="radio"
+                                    key={bitSize.enum}
+                                    name={'compute/guestOS/bitSize'}
+                                    className="radio-field"
+                                    value={bitSize.enum}
+                                    label={bitSize.title}
+                                    onChange={bit =>
+                                        onQDataChanged({
+                                            'compute/guestOS/bitSize': Number(
+                                                bit
+                                            )
+                                        })
+                                    }
+                                    isValid={
+                                        qgenericFieldInfo[
+                                            'compute/guestOS/bitSize'
+                                        ].isValid
+                                    }
+                                    errorText={
+                                        qgenericFieldInfo[
+                                            'compute/guestOS/bitSize'
+                                        ].errorText
+                                    }
+                                    checked={
+                                        dataMap['compute/guestOS/bitSize'] ===
+                                        bitSize.enum
+                                    }
+                                />
+                            ))}
+                        </div>
+                    </div>
+                </GridItem>
+                <GridItem colSpan={2} />
+                <GridItem colSpan={2}>
+                    <Input
+                        data-test-id="guestOS-name"
+                        label={i18n('Guest OS')}
+                        type="textarea"
+                        onChange={tools =>
+                            onQDataChanged({ 'compute/guestOS/name': tools })
+                        }
+                        isValid={
+                            qgenericFieldInfo['compute/guestOS/name'].isValid
+                        }
+                        errorText={
+                            qgenericFieldInfo['compute/guestOS/name'].errorText
+                        }
+                        value={dataMap['compute/guestOS/name']}
+                    />
+                </GridItem>
+                <GridItem colSpan={2} lastColInRow>
+                    <Input
+                        data-test-id="guestOS-tools"
+                        type="textarea"
+                        label={i18n('Guest OS Tools:')}
+                        onChange={tools =>
+                            onQDataChanged({ 'compute/guestOS/tools': tools })
+                        }
+                        isValid={
+                            qgenericFieldInfo['compute/guestOS/tools'].isValid
+                        }
+                        errorText={
+                            qgenericFieldInfo['compute/guestOS/tools'].errorText
+                        }
+                        value={dataMap['compute/guestOS/tools']}
+                    />
+                </GridItem>
+            </GridSection>
+        </div>
+    );
 };
 
 export default GuestOs;
index 967c6f7..5451354 100644 (file)
@@ -20,38 +20,77 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-
-const NumberOfVms = ({qgenericFieldInfo, dataMap, onQDataChanged, qValidateData, customValidations}) => {
-       return(
-               <GridSection titleClassName='software-product-compute-number-of-vms' title={i18n('NUMBER OF VMs')}>
-                       <GridItem>
-                               <Input
-                                       data-test-id='numOfVMs-minimum'
-                                       type='number'
-                                       label={i18n('Minimum')}
-                                       onChange={(tools) => { onQDataChanged({'compute/numOfVMs/minimum' : tools}, customValidations);
-                                               qValidateData({'compute/numOfVMs/maximum' : dataMap['compute/numOfVMs/maximum']}, customValidations); } }
-                                       isValid={qgenericFieldInfo['compute/numOfVMs/minimum'].isValid}
-                                       errorText={qgenericFieldInfo['compute/numOfVMs/minimum'].errorText}
-                                       value={dataMap['compute/numOfVMs/minimum']} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       data-test-id='numOfVMs-maximum'
-                                       type='number'
-                                       label={i18n('Maximum')}
-                                       onChange={(tools) => { onQDataChanged({'compute/numOfVMs/maximum' : tools}, customValidations);
-                                               qValidateData({'compute/numOfVMs/minimum' : dataMap['compute/numOfVMs/minimum']}, customValidations); } }
-                                       isValid={qgenericFieldInfo['compute/numOfVMs/maximum'].isValid}
-                                       errorText={qgenericFieldInfo['compute/numOfVMs/maximum'].errorText}
-                                       value={dataMap['compute/numOfVMs/maximum']} />
-                       </GridItem>
-               </GridSection>
-       );
+const NumberOfVms = ({
+    qgenericFieldInfo,
+    dataMap,
+    onQDataChanged,
+    qValidateData,
+    customValidations
+}) => {
+    return (
+        <GridSection
+            titleClassName="software-product-compute-number-of-vms"
+            title={i18n('NUMBER OF VMs')}>
+            <GridItem>
+                <Input
+                    data-test-id="numOfVMs-minimum"
+                    type="number"
+                    label={i18n('Minimum')}
+                    onChange={tools => {
+                        onQDataChanged(
+                            { 'compute/numOfVMs/minimum': tools },
+                            customValidations
+                        );
+                        qValidateData(
+                            {
+                                'compute/numOfVMs/maximum':
+                                    dataMap['compute/numOfVMs/maximum']
+                            },
+                            customValidations
+                        );
+                    }}
+                    isValid={
+                        qgenericFieldInfo['compute/numOfVMs/minimum'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['compute/numOfVMs/minimum'].errorText
+                    }
+                    value={dataMap['compute/numOfVMs/minimum']}
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    data-test-id="numOfVMs-maximum"
+                    type="number"
+                    label={i18n('Maximum')}
+                    onChange={tools => {
+                        onQDataChanged(
+                            { 'compute/numOfVMs/maximum': tools },
+                            customValidations
+                        );
+                        qValidateData(
+                            {
+                                'compute/numOfVMs/minimum':
+                                    dataMap['compute/numOfVMs/minimum']
+                            },
+                            customValidations
+                        );
+                    }}
+                    isValid={
+                        qgenericFieldInfo['compute/numOfVMs/maximum'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['compute/numOfVMs/maximum'].errorText
+                    }
+                    value={dataMap['compute/numOfVMs/maximum']}
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 NumberOfVms.propTypes = {
-       minNumberOfVMsSelectedByUser: PropTypes.number
+    minNumberOfVMsSelectedByUser: PropTypes.number
 };
 
 export default NumberOfVms;
index 41728ee..58c27c6 100644 (file)
@@ -19,14 +19,14 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
 export const COMPUTE_FLAVOR_FORM = 'COMPUTE_FLAVOR_FORM';
 
 export const actionTypes = keyMirror({
-       ADD_COMPUTE: null,
-       COMPUTE_FLAVORS_LIST_LOADED: null,
-       COMPUTE_LIST_EDIT: null,
-       EDIT_COMPUTE_FLAVOR: null,
-       DELETE_COMPUTE: null,
-       CONFIRM_DELETE_COMPUTE: null,
-       computeEditor: {
-               LOAD_EDITOR_DATA: null,
-               CLEAR_DATA: null
-       }
+    ADD_COMPUTE: null,
+    COMPUTE_FLAVORS_LIST_LOADED: null,
+    COMPUTE_LIST_EDIT: null,
+    EDIT_COMPUTE_FLAVOR: null,
+    DELETE_COMPUTE: null,
+    CONFIRM_DELETE_COMPUTE: null,
+    computeEditor: {
+        LOAD_EDITOR_DATA: null,
+        CLEAR_DATA: null
+    }
 });
index a3ba5fb..06f9e8f 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ComputeFlavorEditorView from './ComputeFlavorEditorView.jsx';
-import {COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js';
+import { COMPUTE_FLAVOR_FORM } from './ComputeFlavorConstants.js';
 import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
-import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { COMPONENTS_COMPUTE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { onboardingMethod } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
 export const mapStateToProps = ({
-       softwareProduct: {
-               softwareProductEditor,
-               softwareProductComponents: {computeFlavor: {computeEditor = {}}}
-       },
-       currentScreen: {
-               props: {isReadOnlyMode}
-       }
+    softwareProduct: {
+        softwareProductEditor,
+        softwareProductComponents: { computeFlavor: { computeEditor = {} } }
+    },
+    currentScreen: { props: { isReadOnlyMode } }
 }) => {
-       const {data: currentSoftwareProduct = {}} = softwareProductEditor;
-       let {data , qdata, qgenericFieldInfo, dataMap, genericFieldInfo, formReady} = computeEditor;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    const { data: currentSoftwareProduct = {} } = softwareProductEditor;
+    let {
+        data,
+        qdata,
+        qgenericFieldInfo,
+        dataMap,
+        genericFieldInfo,
+        formReady
+    } = computeEditor;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       return {
-               data,
-               qdata,
-               qgenericFieldInfo,
-               dataMap,
-               genericFieldInfo,
-               isReadOnlyMode,
-               isFormValid,
-               formReady,
-               isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
-       };
+    return {
+        data,
+        qdata,
+        qgenericFieldInfo,
+        dataMap,
+        genericFieldInfo,
+        isReadOnlyMode,
+        isFormValid,
+        formReady,
+        isManual:
+            currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
+    };
 };
 
-
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: COMPUTE_FLAVOR_FORM}),
-               onQDataChanged: deltaData => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_COMPUTE_QUESTIONNAIRE}),
-               onCancel: () => ComputeFlavorActionHelper.closeComputeEditor(dispatch),
-               onSubmit: ({data, qdata}) => ComputeFlavorActionHelper.saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data, qdata, version}),
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, COMPUTE_FLAVOR_FORM)
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: COMPUTE_FLAVOR_FORM
+            }),
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_COMPUTE_QUESTIONNAIRE
+            }),
+        onCancel: () => ComputeFlavorActionHelper.closeComputeEditor(dispatch),
+        onSubmit: ({ data, qdata }) =>
+            ComputeFlavorActionHelper.saveComputeDataAndQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    componentId,
+                    data,
+                    qdata,
+                    version
+                }
+            ),
+        onValidateForm: () =>
+            ValidationHelper.validateForm(dispatch, COMPUTE_FLAVOR_FORM)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(ComputeFlavorEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    ComputeFlavorEditorView
+);
index e542ce1..840f722 100644 (file)
@@ -23,75 +23,112 @@ import VmSizing from './VmSizing.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 class ComputeEditorView extends React.Component {
+    static propTypes = {
+        data: PropTypes.object,
+        qdata: PropTypes.object,
+        qschema: PropTypes.object,
+        isReadOnlyMode: PropTypes.bool,
+        isManual: PropTypes.bool,
+        onDataChanged: PropTypes.func.isRequired,
+        onQDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               data: PropTypes.object,
-               qdata: PropTypes.object,
-               qschema: PropTypes.object,
-               isReadOnlyMode: PropTypes.bool,
-               isManual: PropTypes.bool,
-               onDataChanged: PropTypes.func.isRequired,
-               onQDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
+    render() {
+        let {
+            data = {},
+            qdata = {},
+            qgenericFieldInfo,
+            dataMap,
+            genericFieldInfo,
+            isReadOnlyMode,
+            isManual,
+            isFormValid,
+            formReady,
+            onDataChanged,
+            onQDataChanged,
+            onSubmit,
+            onCancel,
+            onValidateForm
+        } = this.props;
+        const { id, name, description } = data;
+        const edittingComputeMode = Boolean(id);
 
-       render() {
-               let {data = {}, qdata = {}, qgenericFieldInfo, dataMap, genericFieldInfo, isReadOnlyMode, isManual, isFormValid, formReady,
-                       onDataChanged, onQDataChanged, onSubmit, onCancel, onValidateForm} = this.props;
-               const {id, name, description} = data;
-               const edittingComputeMode = Boolean(id);
+        return (
+            <div className="vsp-component-computeFlavor-view">
+                {genericFieldInfo && (
+                    <Form
+                        ref={form => {
+                            this.form = form;
+                        }}
+                        hasButtons={true}
+                        onSubmit={() => onSubmit({ data, qdata })}
+                        onReset={() => onCancel()}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        isValid={isFormValid}
+                        formReady={formReady}
+                        onValidateForm={() => onValidateForm()}
+                        className="component-questionnaire-validation-form"
+                        submitButtonText={
+                            edittingComputeMode ? i18n('Save') : i18n('Create')
+                        }>
+                        <GridSection hasLostColSet>
+                            <GridItem
+                                colSpan={edittingComputeMode ? 2 : 4}
+                                lastColInRow={!edittingComputeMode}>
+                                <Input
+                                    disabled={!isManual}
+                                    data-test-id="name"
+                                    type="text"
+                                    label={i18n('Flavor Name')}
+                                    value={name}
+                                    onChange={name => onDataChanged({ name })}
+                                    isValid={genericFieldInfo['name'].isValid}
+                                    errorText={
+                                        genericFieldInfo['name'].errorText
+                                    }
+                                    isRequired
+                                />
+                            </GridItem>
+                            <GridItem
+                                colSpan={edittingComputeMode ? 2 : 4}
+                                lastColInRow>
+                                <Input
+                                    data-test-id="description"
+                                    type="textarea"
+                                    label={i18n('Description')}
+                                    value={description}
+                                    onChange={description =>
+                                        onDataChanged({ description })
+                                    }
+                                    isValid={
+                                        genericFieldInfo['description'].isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo['description']
+                                            .errorText
+                                    }
+                                />
+                            </GridItem>
+                        </GridSection>
+                        {edittingComputeMode && (
+                            <VmSizing
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                        )}
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-               return (
-                       <div className='vsp-component-computeFlavor-view'>
-                               {genericFieldInfo && <Form
-                                       ref={(form) => {
-                                               this.form = form;
-                                       }}
-                                       hasButtons={true}
-                                       onSubmit={ () => onSubmit({data, qdata}) }
-                                       onReset={ () => onCancel() }
-                                       labledButtons={true}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       isValid={isFormValid}
-                                       formReady={formReady}
-                                       onValidateForm={() => onValidateForm() }
-                                       className='component-questionnaire-validation-form'
-                                       submitButtonText={edittingComputeMode ? i18n('Save') : i18n('Create')}>
-                                       <GridSection hasLostColSet>
-                                               <GridItem colSpan={edittingComputeMode ? 2 : 4} lastColInRow={!edittingComputeMode}>
-                                                       <Input
-                                                               disabled={!isManual}
-                                                               data-test-id='name'
-                                                               type='text'
-                                                               label={i18n('Flavor Name')}
-                                                               value={name}
-                                                               onChange={name => onDataChanged({name})}
-                                                               isValid={genericFieldInfo['name'].isValid}
-                                                               errorText={genericFieldInfo['name'].errorText}
-                                                               isRequired/>
-                                                       </GridItem>
-                                                       <GridItem colSpan={edittingComputeMode ? 2 : 4} lastColInRow>
-                                                       <Input
-                                                               data-test-id='description'
-                                                               type='textarea'
-                                                               label={i18n('Description')}
-                                                               value={description}
-                                                               onChange={description => onDataChanged({description})}
-                                                               isValid={genericFieldInfo['description'].isValid}
-                                                               errorText={genericFieldInfo['description'].errorText}/>
-                                               </GridItem>
-                                       </GridSection>
-                                       {edittingComputeMode && <VmSizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>}
-                               </Form>
-                               }
-                       </div>
-               );
-       }
-
-       save(){
-               return this.form.handleFormSubmit(new Event('dummy'));
-       }
+    save() {
+        return this.form.handleFormSubmit(new Event('dummy'));
+    }
 }
 
 export default ComputeEditorView;
index 6c02f36..b691084 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes} from './ComputeFlavorConstants.js';
+import { actionTypes } from './ComputeFlavorConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.COMPUTE_FLAVORS_LIST_LOADED:
-                       return [...action.response.results];
-               case actionTypes.ADD_COMPUTE:
-                       return [...state, action.compute];
-               case actionTypes.COMPUTE_LIST_EDIT:
-                       const indexForEdit = state.findIndex(({id}) => id === action.compute.id);
-                       return [...state.slice(0, indexForEdit), action.compute, ...state.slice(indexForEdit + 1)];
-               case actionTypes.DELETE_COMPUTE:
-                       return state.filter(({id}) => id !== action.computeId);
-               default:
-                       return state;
-       }
-};
\ No newline at end of file
+    switch (action.type) {
+        case actionTypes.COMPUTE_FLAVORS_LIST_LOADED:
+            return [...action.response.results];
+        case actionTypes.ADD_COMPUTE:
+            return [...state, action.compute];
+        case actionTypes.COMPUTE_LIST_EDIT:
+            const indexForEdit = state.findIndex(
+                ({ id }) => id === action.compute.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.compute,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.DELETE_COMPUTE:
+            return state.filter(({ id }) => id !== action.computeId);
+        default:
+            return state;
+    }
+};
index a476f85..00d76ef 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js';
+import { actionTypes, COMPUTE_FLAVOR_FORM } from './ComputeFlavorConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.computeEditor.LOAD_EDITOR_DATA:
-                       return {
-                               ...state,
-                               formName: COMPUTE_FLAVOR_FORM,
-                               data: action.compute,
-                               formReady: null,
-                               genericFieldInfo: {
-                                       name: {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true }]
-                                       },
-                                       description: {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 300}]
-                                       }
-                               }
-                       };
-               case actionTypes.computeEditor.CLEAR_DATA:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.computeEditor.LOAD_EDITOR_DATA:
+            return {
+                ...state,
+                formName: COMPUTE_FLAVOR_FORM,
+                data: action.compute,
+                formReady: null,
+                genericFieldInfo: {
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 300 }]
+                    }
+                }
+            };
+        case actionTypes.computeEditor.CLEAR_DATA:
+            return {};
+        default:
+            return state;
+    }
 };
-
index 54f22e0..2f40706 100644 (file)
@@ -18,89 +18,146 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-const VmSizing = ({qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return(
-               <GridSection title={i18n('VM Sizing')} hasLastColSet>
-                       <GridItem>
-                               <Input
-                                       data-test-id='numOfCPUs'
-                                       type='number'
-                                       label={i18n('Number of CPUs')}
-                                       onChange={(tools) => onQDataChanged({'vmSizing/numOfCPUs' : tools})}
-                                       isValid={qgenericFieldInfo['vmSizing/numOfCPUs'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/numOfCPUs'].errorText}
-                                       value={dataMap['vmSizing/numOfCPUs']} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       data-test-id='fileSystemSizeGB'
-                                       type='number'
-                                       label={i18n('File System Size (GB)')}
-                                       onChange={(tools) => onQDataChanged({'vmSizing/fileSystemSizeGB' : tools})}
-                                       isValid={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].errorText}
-                                       value={dataMap['vmSizing/fileSystemSizeGB']} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       data-test-id='persistentStorageVolumeSize'
-                                       type='number'
-                                       label={i18n('Persistent Storage/Volume Size (GB)')}
-                                       onChange={(tools) => onQDataChanged({'vmSizing/persistentStorageVolumeSize' : tools})}
-                                       isValid={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].errorText}
-                                       value={dataMap['vmSizing/persistentStorageVolumeSize']} />
-                       </GridItem>
-                       <GridItem lastColInRow>
-                               <Input
-                                       data-test-id='ioOperationsPerSec'
-                                       type='number'
-                                       label={i18n('I/O Operations (per second)')}
-                                       onChange={(tools) => onQDataChanged({'vmSizing/ioOperationsPerSec' : tools})}
-                                       isValid={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].errorText}
-                                       value={dataMap['vmSizing/ioOperationsPerSec']} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       data-test-id='numOfVMs-cpuOverSubscriptionRatio'
-                                       label={i18n('CPU Oversubscription Ratio')}
-                                       type='select'
-                                       groupClassName='bootstrap-input-options'
-                                       className='input-options-select'
-                                       isValid={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].errorText}
-                                       value={dataMap['vmSizing/cpuOverSubscriptionRatio']}
-                                       onChange={(e) => {
-                                               const selectedIndex = e.target.selectedIndex;
-                                               const val = e.target.options[selectedIndex].value;
-                                               onQDataChanged({'vmSizing/cpuOverSubscriptionRatio' : val});}
-                                       }>
-                                       <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                       {qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].enum.map(cpuOSR => <option value={cpuOSR.enum} key={cpuOSR.enum}>{cpuOSR.title}</option>)}
-                               </Input>
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       data-test-id='numOfVMs-memoryRAM'
-                                       type='select'
-                                       label={i18n('Memory - RAM')}
-                                       groupClassName='bootstrap-input-options'
-                                       className='input-options-select'
-                                       isValid={qgenericFieldInfo['vmSizing/memoryRAM'].isValid}
-                                       errorText={qgenericFieldInfo['vmSizing/memoryRAM'].errorText}
-                                       value={dataMap['vmSizing/memoryRAM']}
-                                       onChange={(e) => {
-                                               const selectedIndex = e.target.selectedIndex;
-                                               const val = e.target.options[selectedIndex].value;
-                                               onQDataChanged({'vmSizing/memoryRAM' : val});}
-                                       }>
-                                       <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                       {qgenericFieldInfo['vmSizing/memoryRAM'].enum.map(mRAM => <option value={mRAM.enum} key={mRAM.enum}>{mRAM.title}</option>)}
-                               </Input>
-                       </GridItem>
-               </GridSection>
-       );
+const VmSizing = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => {
+    return (
+        <GridSection title={i18n('VM Sizing')} hasLastColSet>
+            <GridItem>
+                <Input
+                    data-test-id="numOfCPUs"
+                    type="number"
+                    label={i18n('Number of CPUs')}
+                    onChange={tools =>
+                        onQDataChanged({ 'vmSizing/numOfCPUs': tools })
+                    }
+                    isValid={qgenericFieldInfo['vmSizing/numOfCPUs'].isValid}
+                    errorText={
+                        qgenericFieldInfo['vmSizing/numOfCPUs'].errorText
+                    }
+                    value={dataMap['vmSizing/numOfCPUs']}
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    data-test-id="fileSystemSizeGB"
+                    type="number"
+                    label={i18n('File System Size (GB)')}
+                    onChange={tools =>
+                        onQDataChanged({ 'vmSizing/fileSystemSizeGB': tools })
+                    }
+                    isValid={
+                        qgenericFieldInfo['vmSizing/fileSystemSizeGB'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['vmSizing/fileSystemSizeGB'].errorText
+                    }
+                    value={dataMap['vmSizing/fileSystemSizeGB']}
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    data-test-id="persistentStorageVolumeSize"
+                    type="number"
+                    label={i18n('Persistent Storage/Volume Size (GB)')}
+                    onChange={tools =>
+                        onQDataChanged({
+                            'vmSizing/persistentStorageVolumeSize': tools
+                        })
+                    }
+                    isValid={
+                        qgenericFieldInfo[
+                            'vmSizing/persistentStorageVolumeSize'
+                        ].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo[
+                            'vmSizing/persistentStorageVolumeSize'
+                        ].errorText
+                    }
+                    value={dataMap['vmSizing/persistentStorageVolumeSize']}
+                />
+            </GridItem>
+            <GridItem lastColInRow>
+                <Input
+                    data-test-id="ioOperationsPerSec"
+                    type="number"
+                    label={i18n('I/O Operations (per second)')}
+                    onChange={tools =>
+                        onQDataChanged({ 'vmSizing/ioOperationsPerSec': tools })
+                    }
+                    isValid={
+                        qgenericFieldInfo['vmSizing/ioOperationsPerSec'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['vmSizing/ioOperationsPerSec']
+                            .errorText
+                    }
+                    value={dataMap['vmSizing/ioOperationsPerSec']}
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    data-test-id="numOfVMs-cpuOverSubscriptionRatio"
+                    label={i18n('CPU Oversubscription Ratio')}
+                    type="select"
+                    groupClassName="bootstrap-input-options"
+                    className="input-options-select"
+                    isValid={
+                        qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio']
+                            .isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio']
+                            .errorText
+                    }
+                    value={dataMap['vmSizing/cpuOverSubscriptionRatio']}
+                    onChange={e => {
+                        const selectedIndex = e.target.selectedIndex;
+                        const val = e.target.options[selectedIndex].value;
+                        onQDataChanged({
+                            'vmSizing/cpuOverSubscriptionRatio': val
+                        });
+                    }}>
+                    <option key="placeholder" value="">
+                        {i18n('Select...')}
+                    </option>
+                    {qgenericFieldInfo[
+                        'vmSizing/cpuOverSubscriptionRatio'
+                    ].enum.map(cpuOSR => (
+                        <option value={cpuOSR.enum} key={cpuOSR.enum}>
+                            {cpuOSR.title}
+                        </option>
+                    ))}
+                </Input>
+            </GridItem>
+            <GridItem>
+                <Input
+                    data-test-id="numOfVMs-memoryRAM"
+                    type="select"
+                    label={i18n('Memory - RAM')}
+                    groupClassName="bootstrap-input-options"
+                    className="input-options-select"
+                    isValid={qgenericFieldInfo['vmSizing/memoryRAM'].isValid}
+                    errorText={
+                        qgenericFieldInfo['vmSizing/memoryRAM'].errorText
+                    }
+                    value={dataMap['vmSizing/memoryRAM']}
+                    onChange={e => {
+                        const selectedIndex = e.target.selectedIndex;
+                        const val = e.target.options[selectedIndex].value;
+                        onQDataChanged({ 'vmSizing/memoryRAM': val });
+                    }}>
+                    <option key="placeholder" value="">
+                        {i18n('Select...')}
+                    </option>
+                    {qgenericFieldInfo['vmSizing/memoryRAM'].enum.map(mRAM => (
+                        <option value={mRAM.enum} key={mRAM.enum}>
+                            {mRAM.title}
+                        </option>
+                    ))}
+                </Input>
+            </GridItem>
+        </GridSection>
+    );
 };
 
 export default VmSizing;
index 9f59cd5..d831765 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentCreationView from './SoftwareProductComponentCreationView.jsx';
 import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {forms} from '../SoftwareProductComponentsConstants.js';
+import { forms } from '../SoftwareProductComponentsConstants.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductComponents: {componentEditor: {data, genericFieldInfo, formReady}}} = softwareProduct;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-       return {
-               data,
-               genericFieldInfo,
-               formReady,
-               isFormValid
-       };
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductComponents: {
+            componentEditor: { data, genericFieldInfo, formReady }
+        }
+    } = softwareProduct;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    return {
+        data,
+        genericFieldInfo,
+        formReady,
+        isFormValid
+    };
 };
 
-
-const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.CREATE_FORM}),
-               //onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}),
-               onSubmit: (componentData) => {
-                       return SoftwareProductComponentsActionHelper.createSoftwareProductComponent(dispatch,
-                       {softwareProductId, componentData, version});
-               },
-               onCancel: () => SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch),
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
-
+const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: forms.CREATE_FORM
+            }),
+        //onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}),
+        onSubmit: componentData => {
+            return SoftwareProductComponentsActionHelper.createSoftwareProductComponent(
+                dispatch,
+                { softwareProductId, componentData, version }
+            );
+        },
+        onCancel: () =>
+            SoftwareProductComponentsActionHelper.closeComponentCreationModal(
+                dispatch
+            ),
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentCreationView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductComponentCreationView
+);
index 42804ce..0b33b40 100644 (file)
@@ -21,59 +21,80 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {forms} from '../SoftwareProductComponentsConstants.js';
+import { forms } from '../SoftwareProductComponentsConstants.js';
 
 class ComponentCreationView extends React.Component {
-       render() {
-               let {data = {}, onDataChanged, onCancel, genericFieldInfo} = this.props;
-               let {displayName, description} = data;
-               return(
-                       <div>
-                               {
-                                       genericFieldInfo && <Form
-                                               ref='validationForm'
-                                               hasButtons={true}
-                                               onSubmit={ () => this.submit() }
-                                               onReset={ () => onCancel() }
-                                               submitButtonText={i18n('Create')}
-                                               labledButtons={true}
-                                               isValid={this.props.isFormValid}
-                                               formReady={this.props.formReady}
-                                               onValidateForm={() => this.props.onValidateForm(forms.CREATE_FORM) }
-                                               className='entitlement-pools-form'>
-                                               <GridSection hasLastColSet>
-                                                       <GridItem colSpan={4} lastColInRow>
-                                                               <Input
-                                                                       data-test-id='name'
-                                                                       onChange={displayName => onDataChanged({displayName})}
-                                                                       label={i18n('Name')}
-                                                                       isRequired={true}
-                                                                       isValid={genericFieldInfo.displayName.isValid}
-                                                                       errorText={genericFieldInfo.displayName.errorText}
-                                                                       value={displayName}
-                                                                       type='text'/>
-                                                       </GridItem>
-                                                       <GridItem colSpan={4} lastColInRow>
-                                                               <Input
-                                                                       label={i18n('Description')}
-                                                                       onChange={description => onDataChanged({description})}
-                                                                       value={description}
-                                                                       isValid={genericFieldInfo.description.isValid}
-                                                                       errorText={genericFieldInfo.description.errorText}
-                                                                       data-test-id='description'
-                                                                       type='textarea'/>
-                                                       </GridItem>
-                                               </GridSection>
-                                       </Form>
-                               }
-                       </div>
-               );
-       }
+    render() {
+        let {
+            data = {},
+            onDataChanged,
+            onCancel,
+            genericFieldInfo
+        } = this.props;
+        let { displayName, description } = data;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        submitButtonText={i18n('Create')}
+                        labledButtons={true}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() =>
+                            this.props.onValidateForm(forms.CREATE_FORM)
+                        }
+                        className="entitlement-pools-form">
+                        <GridSection hasLastColSet>
+                            <GridItem colSpan={4} lastColInRow>
+                                <Input
+                                    data-test-id="name"
+                                    onChange={displayName =>
+                                        onDataChanged({ displayName })
+                                    }
+                                    label={i18n('Name')}
+                                    isRequired={true}
+                                    isValid={
+                                        genericFieldInfo.displayName.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.displayName.errorText
+                                    }
+                                    value={displayName}
+                                    type="text"
+                                />
+                            </GridItem>
+                            <GridItem colSpan={4} lastColInRow>
+                                <Input
+                                    label={i18n('Description')}
+                                    onChange={description =>
+                                        onDataChanged({ description })
+                                    }
+                                    value={description}
+                                    isValid={
+                                        genericFieldInfo.description.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.description.errorText
+                                    }
+                                    data-test-id="description"
+                                    type="textarea"
+                                />
+                            </GridItem>
+                        </GridSection>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       submit() {
-               const {onSubmit, data} = this.props;
-               onSubmit(data);
-       }
+    submit() {
+        const { onSubmit, data } = this.props;
+        onSubmit(data);
+    }
 }
 
 export default ComponentCreationView;
index 8c06fd0..f3f64e4 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentsGeneralView from './SoftwareProductComponentsGeneralView.jsx';
 import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 
-import {forms, COMPONENTS_QUESTIONNAIRE} from '../SoftwareProductComponentsConstants.js';
-import {onboardingMethod} from '../../SoftwareProductConstants.js';
+import {
+    forms,
+    COMPONENTS_QUESTIONNAIRE
+} from '../SoftwareProductComponentsConstants.js';
+import { onboardingMethod } from '../../SoftwareProductConstants.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
-       let {componentEditor: {data: componentData = {} , qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap, genericFieldInfo}} = softwareProductComponents;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: { data: currentVSP },
+        softwareProductComponents
+    } = softwareProduct;
+    let {
+        componentEditor: {
+            data: componentData = {},
+            qdata,
+            qgenericFieldInfo: qGenericFieldInfo,
+            dataMap,
+            genericFieldInfo
+        }
+    } = softwareProductComponents;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       return {
-               componentData,
-               qdata,
-               isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL,
-               genericFieldInfo,
-               qGenericFieldInfo,
-               dataMap,
-               isFormValid
-       };
+    return {
+        componentData,
+        qdata,
+        isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL,
+        genericFieldInfo,
+        qGenericFieldInfo,
+        dataMap,
+        isFormValid
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.ALL_SPC_FORMS}),
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
-               onSubmit: ({componentData, qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch,
-                       {softwareProductId, version, vspComponentId: componentId, componentData, qdata});
-               },
-               onValidityChanged: isValidityData => SoftwareProductActionHelper.setIsValidityData(dispatch, {isValidityData})
-       };
-
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: forms.ALL_SPC_FORMS
+            }),
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onSubmit: ({ componentData, qdata }) => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    vspComponentId: componentId,
+                    componentData,
+                    qdata
+                }
+            );
+        },
+        onValidityChanged: isValidityData =>
+            SoftwareProductActionHelper.setIsValidityData(dispatch, {
+                isValidityData
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsGeneralView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsGeneralView);
index 6aa51d1..ad1fcaa 100644 (file)
@@ -21,9 +21,18 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const GeneralSection = ({onDataChanged, displayName, vfcCode, nfcFunction, description, isReadOnlyMode, genericFieldInfo, isManual}) => (
-       <GridSection title={i18n('General')}>
-               {/* disabled until backend will be ready to implement it
+const GeneralSection = ({
+    onDataChanged,
+    displayName,
+    vfcCode,
+    nfcFunction,
+    description,
+    isReadOnlyMode,
+    genericFieldInfo,
+    isManual
+}) => (
+    <GridSection title={i18n('General')}>
+        {/* disabled until backend will be ready to implement it
                        <div className='validation-input-wrapper'>
                        <div className='form-group'>
                        <label className='control-label'>{i18n('Name')}</label>
@@ -32,156 +41,248 @@ const GeneralSection = ({onDataChanged, displayName, vfcCode, nfcFunction, descr
                        </div>
 
                */}
-               <GridItem>
-                       <Input
-                               data-test-id='name'
-                               label={i18n('Name')}
-                               value={displayName}
-                               disabled={!isManual || isReadOnlyMode}
-                               type='text'/>
-                       {!isManual  && <Input
-                               data-test-id='vfcCode'
-                               label={i18n('Naming Code')}
-                               value={vfcCode}
-                               isValid={genericFieldInfo.vfcCode.isValid}
-                               errorText={genericFieldInfo.vfcCode.errorText}
-                               onChange={vfcCode => onDataChanged({vfcCode})}
-                               disabled={isReadOnlyMode}
-                               type='text'/> }
-                       <Input
-                               data-test-id='nfcFunction'
-                               label={i18n('Function')}
-                               value={nfcFunction}
-                               isValid={genericFieldInfo.nfcFunction.isValid}
-                               errorText={genericFieldInfo.nfcFunction.errorText}
-                               onChange={nfcFunction => onDataChanged({nfcFunction})}
-                               disabled={isReadOnlyMode}
-                               type='text'/>
-               </GridItem>
-               <GridItem colSpan={2}>
-                       <Input
-                               label={i18n('Description')}
-                               isValid={genericFieldInfo.description.isValid}
-                               errorText={genericFieldInfo.description.errorText}
-                               onChange={description => onDataChanged({description})}
-                               disabled={isReadOnlyMode}
-                               value={description}
-                               groupClassName='multi-line-textarea'
-                               data-test-id='description'
-                               type='textarea'/>
-               </GridItem>
-               <GridItem />
-       </GridSection>
+        <GridItem>
+            <Input
+                data-test-id="name"
+                label={i18n('Name')}
+                value={displayName}
+                disabled={!isManual || isReadOnlyMode}
+                type="text"
+            />
+            {!isManual && (
+                <Input
+                    data-test-id="vfcCode"
+                    label={i18n('Naming Code')}
+                    value={vfcCode}
+                    isValid={genericFieldInfo.vfcCode.isValid}
+                    errorText={genericFieldInfo.vfcCode.errorText}
+                    onChange={vfcCode => onDataChanged({ vfcCode })}
+                    disabled={isReadOnlyMode}
+                    type="text"
+                />
+            )}
+            <Input
+                data-test-id="nfcFunction"
+                label={i18n('Function')}
+                value={nfcFunction}
+                isValid={genericFieldInfo.nfcFunction.isValid}
+                errorText={genericFieldInfo.nfcFunction.errorText}
+                onChange={nfcFunction => onDataChanged({ nfcFunction })}
+                disabled={isReadOnlyMode}
+                type="text"
+            />
+        </GridItem>
+        <GridItem colSpan={2}>
+            <Input
+                label={i18n('Description')}
+                isValid={genericFieldInfo.description.isValid}
+                errorText={genericFieldInfo.description.errorText}
+                onChange={description => onDataChanged({ description })}
+                disabled={isReadOnlyMode}
+                value={description}
+                groupClassName="multi-line-textarea"
+                data-test-id="description"
+                type="textarea"
+            />
+        </GridItem>
+        <GridItem />
+    </GridSection>
 );
 
-const HypervisorSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Hypervisor')}>
-               <GridItem>
-                       <Input
-                               data-test-id='hypervisor'
-                               label={i18n('Supported Hypervisors')}
-                               type='select'
-                               className='input-options-select'
-                               groupClassName='bootstrap-input-options'
-                               isValid={qgenericFieldInfo['general/hypervisor/hypervisor'].isValid}
-                               errorText={qgenericFieldInfo['general/hypervisor/hypervisor'].errorText}
-                               value={dataMap['general/hypervisor/hypervisor']}
-                               onChange={(e) => {
-                                       const selectedIndex = e.target.selectedIndex;
-                                       const val = e.target.options[selectedIndex].value;
-                                       onQDataChanged({'general/hypervisor/hypervisor' : val});}
-                               }>
-                               <option key='placeholder' value=''>{i18n('Select...')}</option>
-                               {qgenericFieldInfo['general/hypervisor/hypervisor'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
-                       </Input>
-               </GridItem>
-               <GridItem colSpan={2}>
-                       <Input
-                               data-test-id='drivers'
-                               onChange={(driver) => onQDataChanged({'general/hypervisor/drivers' : driver})}
-                               label={i18n('Hypervisor Drivers')}
-                               type='text'
-                               isValid={qgenericFieldInfo['general/hypervisor/drivers'].isValid}
-                               errorText={qgenericFieldInfo['general/hypervisor/drivers'].errorText}
-                               value={dataMap['general/hypervisor/drivers']}/>
-               </GridItem>
-               <GridItem colSpan={3}>
-                       <Input
-                               data-test-id='containerFeaturesDescription'
-                               label={i18n('Describe Container Features')}
-                               type='textarea'
-                               onChange={(containerFeaturesDescription) => onQDataChanged({'general/hypervisor/containerFeaturesDescription' : containerFeaturesDescription})}
-                               isValid={qgenericFieldInfo['general/hypervisor/containerFeaturesDescription'].isValid}
-                               errorText={qgenericFieldInfo['general/hypervisor/containerFeaturesDescription'].errorText}
-                               value={dataMap['general/hypervisor/containerFeaturesDescription']}/>
-               </GridItem>
-       </GridSection>
+const HypervisorSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => (
+    <GridSection title={i18n('Hypervisor')}>
+        <GridItem>
+            <Input
+                data-test-id="hypervisor"
+                label={i18n('Supported Hypervisors')}
+                type="select"
+                className="input-options-select"
+                groupClassName="bootstrap-input-options"
+                isValid={
+                    qgenericFieldInfo['general/hypervisor/hypervisor'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/hypervisor/hypervisor'].errorText
+                }
+                value={dataMap['general/hypervisor/hypervisor']}
+                onChange={e => {
+                    const selectedIndex = e.target.selectedIndex;
+                    const val = e.target.options[selectedIndex].value;
+                    onQDataChanged({ 'general/hypervisor/hypervisor': val });
+                }}>
+                <option key="placeholder" value="">
+                    {i18n('Select...')}
+                </option>
+                {qgenericFieldInfo['general/hypervisor/hypervisor'].enum.map(
+                    hv => (
+                        <option value={hv.enum} key={hv.enum}>
+                            {hv.title}
+                        </option>
+                    )
+                )}
+            </Input>
+        </GridItem>
+        <GridItem colSpan={2}>
+            <Input
+                data-test-id="drivers"
+                onChange={driver =>
+                    onQDataChanged({ 'general/hypervisor/drivers': driver })
+                }
+                label={i18n('Hypervisor Drivers')}
+                type="text"
+                isValid={
+                    qgenericFieldInfo['general/hypervisor/drivers'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/hypervisor/drivers'].errorText
+                }
+                value={dataMap['general/hypervisor/drivers']}
+            />
+        </GridItem>
+        <GridItem colSpan={3}>
+            <Input
+                data-test-id="containerFeaturesDescription"
+                label={i18n('Describe Container Features')}
+                type="textarea"
+                onChange={containerFeaturesDescription =>
+                    onQDataChanged({
+                        'general/hypervisor/containerFeaturesDescription': containerFeaturesDescription
+                    })
+                }
+                isValid={
+                    qgenericFieldInfo[
+                        'general/hypervisor/containerFeaturesDescription'
+                    ].isValid
+                }
+                errorText={
+                    qgenericFieldInfo[
+                        'general/hypervisor/containerFeaturesDescription'
+                    ].errorText
+                }
+                value={
+                    dataMap['general/hypervisor/containerFeaturesDescription']
+                }
+            />
+        </GridItem>
+    </GridSection>
 );
 
-const ImageSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Disk')}>
-               <GridItem>
-                       <Input
-                               data-test-id='bootDiskSizePerVM'
-                               onChange={(bootDiskSizePerVM) => onQDataChanged({'general/disk/bootDiskSizePerVM' : bootDiskSizePerVM})}
-                               label={i18n('Size of boot disk per VM (GB)')}
-                               type='number'
-                               isValid={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].isValid}
-                               errorText={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].errorText}
-                               value={dataMap['general/disk/bootDiskSizePerVM']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='ephemeralDiskSizePerVM'
-                               onChange={(ephemeralDiskSizePerVM) => onQDataChanged({'general/disk/ephemeralDiskSizePerVM' : ephemeralDiskSizePerVM})}
-                               label={i18n('Size of ephemeral disk per VM (GB)')}
-                               type='number'
-                               isValid={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].isValid}
-                               errorText={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].errorText}
-                               value={dataMap['general/disk/ephemeralDiskSizePerVM']}/>
-               </GridItem>
-       </GridSection>
+const ImageSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => (
+    <GridSection title={i18n('Disk')}>
+        <GridItem>
+            <Input
+                data-test-id="bootDiskSizePerVM"
+                onChange={bootDiskSizePerVM =>
+                    onQDataChanged({
+                        'general/disk/bootDiskSizePerVM': bootDiskSizePerVM
+                    })
+                }
+                label={i18n('Size of boot disk per VM (GB)')}
+                type="number"
+                isValid={
+                    qgenericFieldInfo['general/disk/bootDiskSizePerVM'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/disk/bootDiskSizePerVM']
+                        .errorText
+                }
+                value={dataMap['general/disk/bootDiskSizePerVM']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="ephemeralDiskSizePerVM"
+                onChange={ephemeralDiskSizePerVM =>
+                    onQDataChanged({
+                        'general/disk/ephemeralDiskSizePerVM': ephemeralDiskSizePerVM
+                    })
+                }
+                label={i18n('Size of ephemeral disk per VM (GB)')}
+                type="number"
+                isValid={
+                    qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM']
+                        .errorText
+                }
+                value={dataMap['general/disk/ephemeralDiskSizePerVM']}
+            />
+        </GridItem>
+    </GridSection>
 );
 
-const RecoverySection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Recovery')}>
-               <GridItem>
-                       <Input
-                               data-test-id='pointObjective'
-                               label={i18n('VM Recovery Point Objective (Minutes)')}
-                               type='number'
-                               onChange={(pointObjective) => onQDataChanged({'general/recovery/pointObjective' : pointObjective})}
-                               isValid={qgenericFieldInfo['general/recovery/pointObjective'].isValid}
-                               errorText={qgenericFieldInfo['general/recovery/pointObjective'].errorText}
-                               value={dataMap['general/recovery/pointObjective']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='timeObjective'
-                               label={i18n('VM Recovery Time Objective (Minutes)')}
-                               type='number'
-                               onChange={(timeObjective) => onQDataChanged({'general/recovery/timeObjective' : timeObjective})}
-                               isValid={qgenericFieldInfo['general/recovery/timeObjective'].isValid}
-                               errorText={qgenericFieldInfo['general/recovery/timeObjective'].errorText}
-                               value={dataMap['general/recovery/timeObjective']}/>
-                       <div className='empty-two-col' />
-               </GridItem>
-               <GridItem colSpan={2} />
-               <GridItem colSpan={2}>
-                       <Input
-                               data-test-id='vmProcessFailuresHandling'
-                               className='textarea'
-                               label={i18n('How are in VM process failures handled?')}
-                               type='textarea'
-                               onChange={(vmProcessFailuresHandling) => onQDataChanged({'general/recovery/vmProcessFailuresHandling' : vmProcessFailuresHandling})}
-                               isValid={qgenericFieldInfo['general/recovery/vmProcessFailuresHandling'].isValid}
-                               errorText={qgenericFieldInfo['general/recovery/vmProcessFailuresHandling'].errorText}
-                               value={dataMap['general/recovery/vmProcessFailuresHandling']}/>
-                       <div className='empty-two-col' />
-
-               </GridItem>
-               {
-                       /** disabled until backend will be ready to implement it
+const RecoverySection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => (
+    <GridSection title={i18n('Recovery')}>
+        <GridItem>
+            <Input
+                data-test-id="pointObjective"
+                label={i18n('VM Recovery Point Objective (Minutes)')}
+                type="number"
+                onChange={pointObjective =>
+                    onQDataChanged({
+                        'general/recovery/pointObjective': pointObjective
+                    })
+                }
+                isValid={
+                    qgenericFieldInfo['general/recovery/pointObjective'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/recovery/pointObjective']
+                        .errorText
+                }
+                value={dataMap['general/recovery/pointObjective']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="timeObjective"
+                label={i18n('VM Recovery Time Objective (Minutes)')}
+                type="number"
+                onChange={timeObjective =>
+                    onQDataChanged({
+                        'general/recovery/timeObjective': timeObjective
+                    })
+                }
+                isValid={
+                    qgenericFieldInfo['general/recovery/timeObjective'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['general/recovery/timeObjective']
+                        .errorText
+                }
+                value={dataMap['general/recovery/timeObjective']}
+            />
+            <div className="empty-two-col" />
+        </GridItem>
+        <GridItem colSpan={2} />
+        <GridItem colSpan={2}>
+            <Input
+                data-test-id="vmProcessFailuresHandling"
+                className="textarea"
+                label={i18n('How are in VM process failures handled?')}
+                type="textarea"
+                onChange={vmProcessFailuresHandling =>
+                    onQDataChanged({
+                        'general/recovery/vmProcessFailuresHandling': vmProcessFailuresHandling
+                    })
+                }
+                isValid={
+                    qgenericFieldInfo[
+                        'general/recovery/vmProcessFailuresHandling'
+                    ].isValid
+                }
+                errorText={
+                    qgenericFieldInfo[
+                        'general/recovery/vmProcessFailuresHandling'
+                    ].errorText
+                }
+                value={dataMap['general/recovery/vmProcessFailuresHandling']}
+            />
+            <div className="empty-two-col" />
+        </GridItem>
+        {/** disabled until backend will be ready to implement it
                        <div className='row'>
                        <div className='col-md-3'>
                        <Input
@@ -190,78 +291,127 @@ const RecoverySection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
                        pointer='/general/recovery/VMRecoveryDocument'/>
                        </div>
                        </div>
-                       */
-               }
-       </GridSection>
+                       */}
+    </GridSection>
 );
 
-const DNSConfigurationSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('DNS Configuration')}>
-               <GridItem colSpan={2}>
-                       <Input
-                               data-test-id='dnsConfiguration'
-                               label={i18n('Do you have a need for DNS as a Service? Please describe.')}
-                               type='textarea'
-                               onChange={(dnsConfiguration) => onQDataChanged({'general/dnsConfiguration' : dnsConfiguration})}
-                               isValid={qgenericFieldInfo['general/dnsConfiguration'].isValid}
-                               errorText={qgenericFieldInfo['general/dnsConfiguration'].errorText}
-                               value={dataMap['general/dnsConfiguration']}/>
-               </GridItem>
-       </GridSection>
+const DNSConfigurationSection = ({
+    dataMap,
+    onQDataChanged,
+    qgenericFieldInfo
+}) => (
+    <GridSection title={i18n('DNS Configuration')}>
+        <GridItem colSpan={2}>
+            <Input
+                data-test-id="dnsConfiguration"
+                label={i18n(
+                    'Do you have a need for DNS as a Service? Please describe.'
+                )}
+                type="textarea"
+                onChange={dnsConfiguration =>
+                    onQDataChanged({
+                        'general/dnsConfiguration': dnsConfiguration
+                    })
+                }
+                isValid={qgenericFieldInfo['general/dnsConfiguration'].isValid}
+                errorText={
+                    qgenericFieldInfo['general/dnsConfiguration'].errorText
+                }
+                value={dataMap['general/dnsConfiguration']}
+            />
+        </GridItem>
+    </GridSection>
 );
 
-const CloneSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Clone')}>
-               <GridItem colSpan={2}>
-                       <Input
-                               data-test-id='vmCloneUsage'
-                               label={i18n('Describe VM Clone Use')}
-                               type='textarea'
-                               onChange={(vmCloneUsage) => onQDataChanged({'general/vmCloneUsage' : vmCloneUsage})}
-                               isValid={qgenericFieldInfo['general/vmCloneUsage'].isValid}
-                               errorText={qgenericFieldInfo['general/vmCloneUsage'].errorText}
-                               value={dataMap['general/vmCloneUsage']}/>
-               </GridItem>
-       </GridSection>
+const CloneSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => (
+    <GridSection title={i18n('Clone')}>
+        <GridItem colSpan={2}>
+            <Input
+                data-test-id="vmCloneUsage"
+                label={i18n('Describe VM Clone Use')}
+                type="textarea"
+                onChange={vmCloneUsage =>
+                    onQDataChanged({ 'general/vmCloneUsage': vmCloneUsage })
+                }
+                isValid={qgenericFieldInfo['general/vmCloneUsage'].isValid}
+                errorText={qgenericFieldInfo['general/vmCloneUsage'].errorText}
+                value={dataMap['general/vmCloneUsage']}
+            />
+        </GridItem>
+    </GridSection>
 );
 
 class SoftwareProductComponentsGeneralView extends React.Component {
+    render() {
+        let {
+            isManual,
+            onQDataChanged,
+            onDataChanged,
+            genericFieldInfo,
+            dataMap,
+            qGenericFieldInfo,
+            componentData: { displayName, vfcCode, nfcFunction, description },
+            isReadOnlyMode
+        } = this.props;
+        return (
+            <div className="vsp-components-general">
+                <div className="general-data">
+                    {genericFieldInfo &&
+                        qGenericFieldInfo && (
+                            <Form
+                                isValid={this.props.isFormValid}
+                                formReady={null}
+                                isReadOnlyMode={isReadOnlyMode}
+                                onValidityChanged={isValidityData =>
+                                    this.props.onValidityChanged(isValidityData)
+                                }
+                                hasButtons={false}>
+                                <GeneralSection
+                                    onDataChanged={onDataChanged}
+                                    displayName={displayName}
+                                    vfcCode={vfcCode}
+                                    nfcFunction={nfcFunction}
+                                    description={description}
+                                    isManual={isManual}
+                                    isReadOnlyMode={isReadOnlyMode}
+                                    genericFieldInfo={genericFieldInfo}
+                                />
+                                <HypervisorSection
+                                    onQDataChanged={onQDataChanged}
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qGenericFieldInfo}
+                                />
+                                <ImageSection
+                                    onQDataChanged={onQDataChanged}
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qGenericFieldInfo}
+                                />
+                                <RecoverySection
+                                    onQDataChanged={onQDataChanged}
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qGenericFieldInfo}
+                                />
+                                <DNSConfigurationSection
+                                    onQDataChanged={onQDataChanged}
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qGenericFieldInfo}
+                                />
+                                <CloneSection
+                                    onQDataChanged={onQDataChanged}
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qGenericFieldInfo}
+                                />
+                            </Form>
+                        )}
+                </div>
+            </div>
+        );
+    }
 
-       render() {
-               let {isManual, onQDataChanged, onDataChanged, genericFieldInfo, dataMap, qGenericFieldInfo, componentData: {displayName, vfcCode, nfcFunction, description}, isReadOnlyMode} =  this.props;
-               return(
-                       <div className='vsp-components-general'>
-                               <div className='general-data'>
-                                       {genericFieldInfo && qGenericFieldInfo && <Form
-                                               isValid={this.props.isFormValid}
-                                               formReady={null}
-                                               isReadOnlyMode={isReadOnlyMode}
-                                               onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)}
-                                               hasButtons={false}>
-                                               <GeneralSection
-                                                       onDataChanged={onDataChanged}
-                                                       displayName={displayName}
-                                                       vfcCode={vfcCode}
-                                                       nfcFunction={nfcFunction}
-                                                       description={description}
-                                                       isManual={isManual}
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       genericFieldInfo={genericFieldInfo}/>
-                                               <HypervisorSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                               <ImageSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                               <RecoverySection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                               <DNSConfigurationSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                               <CloneSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                       </Form> }
-                               </div>
-                       </div>
-               );
-       }
-
-       save() {
-               let {onSubmit, componentData, qdata} = this.props;
-               return onSubmit({componentData, qdata});
-       }
+    save() {
+        let { onSubmit, componentData, qdata } = this.props;
+        return onSubmit({ componentData, qdata });
+    }
 }
 
 export default SoftwareProductComponentsGeneralView;
index 2483d0a..900a9a1 100644 (file)
@@ -1,6 +1,6 @@
-
 import Validator from 'nfvo-utils/Validator.js';
 
-export  const imageCustomValidations = {
-       'version': value => Validator.validate('version', value, [{type: 'required', data: true}])
+export const imageCustomValidations = {
+    version: value =>
+        Validator.validate('version', value, [{ type: 'required', data: true }])
 };
index 8d70d6f..3f661b7 100644 (file)
@@ -17,157 +17,268 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js';
-import {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { IMAGE_QUESTIONNAIRE } from './SoftwareProductComponentsImageConstants.js';
+import { actionTypes } from './SoftwareProductComponentsImageConstants.js';
 
 function baseUrl(softwareProductId, version, componentId) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/images`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/images`;
 }
 
-function fetchImagesList({softwareProductId, componentId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
+function fetchImagesList({ softwareProductId, componentId, version }) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version, componentId)}`
+    );
 }
 
-function fetchImage({softwareProductId, componentId, imageId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`);
+function fetchImage({ softwareProductId, componentId, imageId, version }) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version, componentId)}/${imageId}`
+    );
 }
 
-function destroyImage({softwareProductId, componentId, version, imageId}) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`);
+function destroyImage({ softwareProductId, componentId, version, imageId }) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version, componentId)}/${imageId}`
+    );
 }
 
-function createImage({softwareProductId, componentId, version, data}) {
-       return RestAPIUtil.post(baseUrl(softwareProductId, version, componentId), {
-               fileName: data.fileName
-       });
+function createImage({ softwareProductId, componentId, version, data }) {
+    return RestAPIUtil.post(baseUrl(softwareProductId, version, componentId), {
+        fileName: data.fileName
+    });
 }
 
-function fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`);
+function fetchImageQuestionnaire({
+    softwareProductId,
+    componentId,
+    imageId,
+    version
+}) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(
+            softwareProductId,
+            version,
+            componentId
+        )}/${imageId}/questionnaire`
+    );
 }
 
-function saveImage({softwareProductId, version, componentId, image: {id, fileName}}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{
-               fileName
-       });
-
+function saveImage({
+    softwareProductId,
+    version,
+    componentId,
+    image: { id, fileName }
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version, componentId)}/${id}`,
+        {
+            fileName
+        }
+    );
 }
 
-function saveImageQuestionnaire({softwareProductId, componentId, version, imageId, qdata}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`, qdata);
+function saveImageQuestionnaire({
+    softwareProductId,
+    componentId,
+    version,
+    imageId,
+    qdata
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(
+            softwareProductId,
+            version,
+            componentId
+        )}/${imageId}/questionnaire`,
+        qdata
+    );
 }
 
 const SoftwareProductComponentImagesActionHelper = {
-       fetchImagesList(dispatch, {softwareProductId, componentId, version}) {
-               dispatch({
-                       type: actionTypes.IMAGES_LIST_UPDATE,
-                       response: []
-               });
-
-               return fetchImagesList({softwareProductId, componentId, version}).then((response) => {
-                       dispatch({
-                               type: actionTypes.IMAGES_LIST_UPDATE,
-                               response: response.results,
-                               componentId : componentId
-                       });
-               });
-       },
-
-       deleteImage(dispatch, {softwareProductId, componentId, version, imageId}) {
-               return destroyImage({softwareProductId, componentId, version, imageId}).then(() => {
-                       return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
-               });
-       },
-
-       loadImageData({softwareProductId, componentId, imageId, version}) {
-               return fetchImage({softwareProductId, componentId, imageId, version});
-       },
-
-       openEditImageEditor(dispatch, {image, softwareProductId, componentId, version, isReadOnlyMode}) {
-               return SoftwareProductComponentImagesActionHelper.loadImageData({softwareProductId, componentId, imageId: image.id, version}).then(({data}) => {
-                       SoftwareProductComponentImagesActionHelper.loadImageQuestionnaire(dispatch, {
-                               softwareProductId,
-                               componentId,
-                               imageId: image.id,
-                               version
-                       }).then(() => {
-                               SoftwareProductComponentImagesActionHelper.openImageEditor(dispatch, {
-                                       softwareProductId,
-                                       componentId,
-                                       version,
-                                       isReadOnlyMode,
-                                       image,
-                                       data
-                               });
-                       });
-               });
-       },
-
-       openImageEditor(dispatch, {image = {}, data = {}, softwareProductId, componentId, version, isReadOnlyMode}) {
-
-               let {id} = image;
-               let title = id ?  i18n('Edit Image') : i18n('Create New Image');
-               let className = id ? 'image-modal-edit' : 'image-modal-new';
-
-               dispatch({
-                       type: actionTypes.ImageEditor.OPEN,
-                       image: {...data, id}
-               });
-
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR,
-                               title: title,
-                               modalClassName: className,
-                               modalComponentProps: {softwareProductId, componentId, version, isReadOnlyMode}
-                       }
-               });
-
-       },
-
-       closeImageEditor(dispatch) {
-
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-
-               dispatch({
-                       type: actionTypes.ImageEditor.CLOSE
-               });
-
-       },
-
-       loadImageQuestionnaire(dispatch, {softwareProductId, componentId, imageId, version}) {
-               return fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}).then((response) => {
-                       ValidationHelper.qDataLoaded(dispatch, {qName: IMAGE_QUESTIONNAIRE ,response: {
-                               qdata: response.data ? JSON.parse(response.data) : {},
-                               qschema: JSON.parse(response.schema)
-                       }});
-               });
-       },
-
-       saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}) {
-               SoftwareProductComponentImagesActionHelper.closeImageEditor(dispatch);
-               if (data !== null && data.id) {
-                       // editor in edit mode
-                       return Promise.all([
-                               saveImageQuestionnaire({softwareProductId, version, componentId, imageId: data.id, qdata}),
-                               saveImage({softwareProductId, version, componentId, image: data}).then(() => {
-                                       return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
-                               })
-                       ]);
-               } else {
-                       // editor in create mode
-                       createImage({softwareProductId, componentId, version, data}).then(() => {
-                               return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
-                       });
-               }
-       }
+    fetchImagesList(dispatch, { softwareProductId, componentId, version }) {
+        dispatch({
+            type: actionTypes.IMAGES_LIST_UPDATE,
+            response: []
+        });
+
+        return fetchImagesList({
+            softwareProductId,
+            componentId,
+            version
+        }).then(response => {
+            dispatch({
+                type: actionTypes.IMAGES_LIST_UPDATE,
+                response: response.results,
+                componentId: componentId
+            });
+        });
+    },
+
+    deleteImage(
+        dispatch,
+        { softwareProductId, componentId, version, imageId }
+    ) {
+        return destroyImage({
+            softwareProductId,
+            componentId,
+            version,
+            imageId
+        }).then(() => {
+            return SoftwareProductComponentImagesActionHelper.fetchImagesList(
+                dispatch,
+                { softwareProductId, componentId, version }
+            );
+        });
+    },
+
+    loadImageData({ softwareProductId, componentId, imageId, version }) {
+        return fetchImage({ softwareProductId, componentId, imageId, version });
+    },
+
+    openEditImageEditor(
+        dispatch,
+        { image, softwareProductId, componentId, version, isReadOnlyMode }
+    ) {
+        return SoftwareProductComponentImagesActionHelper.loadImageData({
+            softwareProductId,
+            componentId,
+            imageId: image.id,
+            version
+        }).then(({ data }) => {
+            SoftwareProductComponentImagesActionHelper.loadImageQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    componentId,
+                    imageId: image.id,
+                    version
+                }
+            ).then(() => {
+                SoftwareProductComponentImagesActionHelper.openImageEditor(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        componentId,
+                        version,
+                        isReadOnlyMode,
+                        image,
+                        data
+                    }
+                );
+            });
+        });
+    },
+
+    openImageEditor(
+        dispatch,
+        {
+            image = {},
+            data = {},
+            softwareProductId,
+            componentId,
+            version,
+            isReadOnlyMode
+        }
+    ) {
+        let { id } = image;
+        let title = id ? i18n('Edit Image') : i18n('Create New Image');
+        let className = id ? 'image-modal-edit' : 'image-modal-new';
+
+        dispatch({
+            type: actionTypes.ImageEditor.OPEN,
+            image: { ...data, id }
+        });
+
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName:
+                    modalContentMapper.SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR,
+                title: title,
+                modalClassName: className,
+                modalComponentProps: {
+                    softwareProductId,
+                    componentId,
+                    version,
+                    isReadOnlyMode
+                }
+            }
+        });
+    },
+
+    closeImageEditor(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+
+        dispatch({
+            type: actionTypes.ImageEditor.CLOSE
+        });
+    },
+
+    loadImageQuestionnaire(
+        dispatch,
+        { softwareProductId, componentId, imageId, version }
+    ) {
+        return fetchImageQuestionnaire({
+            softwareProductId,
+            componentId,
+            imageId,
+            version
+        }).then(response => {
+            ValidationHelper.qDataLoaded(dispatch, {
+                qName: IMAGE_QUESTIONNAIRE,
+                response: {
+                    qdata: response.data ? JSON.parse(response.data) : {},
+                    qschema: JSON.parse(response.schema)
+                }
+            });
+        });
+    },
+
+    saveImageDataAndQuestionnaire(
+        dispatch,
+        { softwareProductId, componentId, version, data, qdata }
+    ) {
+        SoftwareProductComponentImagesActionHelper.closeImageEditor(dispatch);
+        if (data !== null && data.id) {
+            // editor in edit mode
+            return Promise.all([
+                saveImageQuestionnaire({
+                    softwareProductId,
+                    version,
+                    componentId,
+                    imageId: data.id,
+                    qdata
+                }),
+                saveImage({
+                    softwareProductId,
+                    version,
+                    componentId,
+                    image: data
+                }).then(() => {
+                    return SoftwareProductComponentImagesActionHelper.fetchImagesList(
+                        dispatch,
+                        { softwareProductId, componentId, version }
+                    );
+                })
+            ]);
+        } else {
+            // editor in create mode
+            createImage({ softwareProductId, componentId, version, data }).then(
+                () => {
+                    return SoftwareProductComponentImagesActionHelper.fetchImagesList(
+                        dispatch,
+                        { softwareProductId, componentId, version }
+                    );
+                }
+            );
+        }
+    }
 };
 
 export default SoftwareProductComponentImagesActionHelper;
index 6b6c9a3..300b289 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       IMAGES_LIST_UPDATE: null,
+    IMAGES_LIST_UPDATE: null,
 
-       ImageEditor: {
-               CLOSE: null,
-               OPEN: null
-       }
+    ImageEditor: {
+        CLOSE: null,
+        OPEN: null
+    }
 });
 
 export const IMAGE_QUESTIONNAIRE = 'image';
index c5f23e7..0243a38 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import SoftwareProductComponentsImageActionHelper from './SoftwareProductComponentsImageActionHelper.js';
 import SoftwareProductComponentsImageEditorView from './SoftwareProductComponentsImageEditorView.jsx';
-import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
-import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js';
+import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { IMAGE_QUESTIONNAIRE } from './SoftwareProductComponentsImageConstants.js';
 
 export const mapStateToProps = ({
-       softwareProduct,
-       currentScreen: {props: {isReadOnlyMode}}
+    softwareProduct,
+    currentScreen: { props: { isReadOnlyMode } }
 }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct = {},
+            isValidityData = true
+        },
+        softwareProductComponents
+    } = softwareProduct;
 
-       let {softwareProductEditor: {data:currentSoftwareProduct = {},  isValidityData = true}, softwareProductComponents} = softwareProduct;
-
-       let {images: {imageEditor = {}}} = softwareProductComponents;
-       let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = imageEditor;
-       let {version, onboardingMethod} = currentSoftwareProduct;
-       let isManual =  onboardingMethod === onboardingMethodTypes.MANUAL;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo) &&  ValidationHelper.checkFormValid(qgenericFieldInfo);
-
-       return {
-               version,
-               currentSoftwareProduct,
-               isValidityData,
-               data,
-               qdata,
-               dataMap,
-               isFormValid,
-               formReady,
-               genericFieldInfo,
-               qgenericFieldInfo,
-               isReadOnlyMode,
-               isManual: isManual
-       };
+    let { images: { imageEditor = {} } } = softwareProductComponents;
+    let {
+        data,
+        qdata,
+        genericFieldInfo,
+        qgenericFieldInfo,
+        dataMap,
+        formReady
+    } = imageEditor;
+    let { version, onboardingMethod } = currentSoftwareProduct;
+    let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
+    let isFormValid =
+        ValidationHelper.checkFormValid(genericFieldInfo) &&
+        ValidationHelper.checkFormValid(qgenericFieldInfo);
 
+    return {
+        version,
+        currentSoftwareProduct,
+        isValidityData,
+        data,
+        qdata,
+        dataMap,
+        isFormValid,
+        formReady,
+        genericFieldInfo,
+        qgenericFieldInfo,
+        isReadOnlyMode,
+        isManual: isManual
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.IMAGE_EDIT_FORM}),
-               onSubmit: ({data, qdata}) => SoftwareProductComponentsImageActionHelper.saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}),
-               onCancel: () => SoftwareProductComponentsImageActionHelper.closeImageEditor(dispatch),
-               onValidateForm: customValidations => {
-                       ValidationHelper.validateForm(dispatch, forms.IMAGE_EDIT_FORM);
-                       ValidationHelper.qValidateForm(dispatch, IMAGE_QUESTIONNAIRE, customValidations);
-               },
-               onQDataChanged: (deltaData, customValidations) => ValidationHelper.qDataChanged(dispatch, {deltaData,
-                       qName: IMAGE_QUESTIONNAIRE, customValidations}),
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: forms.IMAGE_EDIT_FORM
+            }),
+        onSubmit: ({ data, qdata }) =>
+            SoftwareProductComponentsImageActionHelper.saveImageDataAndQuestionnaire(
+                dispatch,
+                { softwareProductId, componentId, version, data, qdata }
+            ),
+        onCancel: () =>
+            SoftwareProductComponentsImageActionHelper.closeImageEditor(
+                dispatch
+            ),
+        onValidateForm: customValidations => {
+            ValidationHelper.validateForm(dispatch, forms.IMAGE_EDIT_FORM);
+            ValidationHelper.qValidateForm(
+                dispatch,
+                IMAGE_QUESTIONNAIRE,
+                customValidations
+            );
+        },
+        onQDataChanged: (deltaData, customValidations) =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: IMAGE_QUESTIONNAIRE,
+                customValidations
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentsImageEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductComponentsImageEditorView
+);
index 7c35742..3846d45 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentsImageConstants.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { actionTypes } from './SoftwareProductComponentsImageConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.ImageEditor.CLOSE:
-                       return {};
-               case actionTypes.ImageEditor.OPEN:
-                       return {
-                               ...state,
-                               data: {
-                                       ...action.image
-                               },
-                               genericFieldInfo: {
-                                       'fileName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       }
-                               },
-                               formName: forms.IMAGE_EDIT_FORM
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.ImageEditor.CLOSE:
+            return {};
+        case actionTypes.ImageEditor.OPEN:
+            return {
+                ...state,
+                data: {
+                    ...action.image
+                },
+                genericFieldInfo: {
+                    fileName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    }
+                },
+                formName: forms.IMAGE_EDIT_FORM
+            };
+        default:
+            return state;
+    }
 };
-
index a5ef152..3670ab9 100644 (file)
@@ -21,53 +21,81 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 
 import FileDetails from './imagesEditorComponents/FileDetails.jsx';
 import ImageDetails from './imagesEditorComponents/ImageDetails.jsx';
-import {imageCustomValidations} from './ImageValidations.js';
+import { imageCustomValidations } from './ImageValidations.js';
 
 class SoftwareProductComponentsImageEditorView extends React.Component {
-       static propTypes = {
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
+    static propTypes = {
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       render() {
-               let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, genericFieldInfo, qgenericFieldInfo, dataMap, onDataChanged, isManual, onQDataChanged} = this.props;
-               let {id, fileName} = data;
-               let editingMode = Boolean(id);
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       ref={(form) => { this.form = form; }}
-                                       hasButtons={true}
-                                       onSubmit={ () => this.submit() }
-                                       onReset={ () => onCancel() }
-                                       labledButtons={true}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       isValid={isFormValid}
-                                       formReady={formReady}
-                                       submitButtonText={editingMode ? i18n('Save') : i18n('Create')}
-                                       onValidateForm={() => onValidateForm(imageCustomValidations) }
-                                       className='vsp-components-image-editor'>
-                                       <div className='editor-data'>
-                                               <FileDetails
-                                                       editingMode={editingMode}
-                                                       genericFieldInfo={genericFieldInfo}
-                                                       qgenericFieldInfo={qgenericFieldInfo}
-                                                       fileName={fileName}
-                                                       onDataChanged={onDataChanged}
-                                                       isManual={isManual}
-                                                       dataMap={dataMap}
-                                                       onQDataChanged={onQDataChanged}/>
-                                               {editingMode && <ImageDetails dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>}
-                                       </div>
-                               </Form>}
-                       </div>
-               );
-       }
-       submit() {
-               let {data, qdata, onSubmit, version} = this.props;
-               onSubmit({data, qdata, version});
-       }
+    render() {
+        let {
+            onCancel,
+            onValidateForm,
+            isReadOnlyMode,
+            isFormValid,
+            formReady,
+            data = {},
+            genericFieldInfo,
+            qgenericFieldInfo,
+            dataMap,
+            onDataChanged,
+            isManual,
+            onQDataChanged
+        } = this.props;
+        let { id, fileName } = data;
+        let editingMode = Boolean(id);
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref={form => {
+                            this.form = form;
+                        }}
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        isValid={isFormValid}
+                        formReady={formReady}
+                        submitButtonText={
+                            editingMode ? i18n('Save') : i18n('Create')
+                        }
+                        onValidateForm={() =>
+                            onValidateForm(imageCustomValidations)
+                        }
+                        className="vsp-components-image-editor">
+                        <div className="editor-data">
+                            <FileDetails
+                                editingMode={editingMode}
+                                genericFieldInfo={genericFieldInfo}
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                fileName={fileName}
+                                onDataChanged={onDataChanged}
+                                isManual={isManual}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            {editingMode && (
+                                <ImageDetails
+                                    dataMap={dataMap}
+                                    qgenericFieldInfo={qgenericFieldInfo}
+                                    onQDataChanged={onQDataChanged}
+                                />
+                            )}
+                        </div>
+                    </Form>
+                )}
+            </div>
+        );
+    }
+    submit() {
+        let { data, qdata, onSubmit, version } = this.props;
+        onSubmit({ data, qdata, version });
+    }
 }
 
 export default SoftwareProductComponentsImageEditorView;
index d071647..f3c39c3 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import SoftwareProductComponentsImageListView from './SoftwareProductComponentsImageListView.jsx';
 import ImageHelper from './SoftwareProductComponentsImageActionHelper.js';
 import SoftwareProductComponentsImagesActionHelper from './SoftwareProductComponentsImageActionHelper.js';
 import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
-import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
+import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct = {},
+            isValidityData = true
+        },
+        softwareProductComponents
+    } = softwareProduct;
+    let {
+        images: { imagesList = [] },
+        componentEditor: {
+            data: componentData,
+            qdata,
+            dataMap,
+            qgenericFieldInfo
+        }
+    } = softwareProductComponents;
+    let { onboardingMethod } = currentSoftwareProduct;
+    let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
 
-       let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
-       let {images: {imagesList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
-       let {onboardingMethod} = currentSoftwareProduct;
-       let isManual =  onboardingMethod === onboardingMethodTypes.MANUAL;
-
-       return {
-               componentData,
-               qdata,
-               dataMap,
-               qgenericFieldInfo,
-               isValidityData,
-               imagesList,
-               isManual : isManual
-       };
+    return {
+        componentData,
+        qdata,
+        dataMap,
+        qgenericFieldInfo,
+        isValidityData,
+        imagesList,
+        isManual: isManual
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
-                       qName: COMPONENTS_QUESTIONNAIRE}),
-               onAddImage: (isReadOnlyMode) => {
-                       SoftwareProductComponentsImagesActionHelper.openImageEditor(dispatch,
-                               {isReadOnlyMode, softwareProductId,
-                                       componentId, version}
-                       );},
-               onDeleteImage: (image) => {
-                       let shortenedFileName = (image.fileName.length > 40) ? image.fileName.substr(0,40) + '...' : image.fileName;
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                               data: {
-                                       msg: i18n('Are you sure you want to delete "{shortenedFileName}"?', {shortenedFileName: shortenedFileName}),
-                                       onConfirmed: () => ImageHelper.deleteImage(dispatch, {
-                                               softwareProductId,
-                                               componentId,
-                                               version,
-                                               imageId: image.id
-                                       })
-                               }
-                       });
-               },
-               onEditImageClick: (image, isReadOnlyMode) => {
-                       SoftwareProductComponentsImagesActionHelper.openEditImageEditor(dispatch, {
-                               image, isReadOnlyMode, softwareProductId, componentId, version, modalClassName: 'image-modal-edit'}
-                       );
-               },
-               onSubmit: (qdata) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
-                       {softwareProductId,
-                               vspComponentId: componentId,
-                               version,
-                               qdata});
-               }
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onAddImage: isReadOnlyMode => {
+            SoftwareProductComponentsImagesActionHelper.openImageEditor(
+                dispatch,
+                {
+                    isReadOnlyMode,
+                    softwareProductId,
+                    componentId,
+                    version
+                }
+            );
+        },
+        onDeleteImage: image => {
+            let shortenedFileName =
+                image.fileName.length > 40
+                    ? image.fileName.substr(0, 40) + '...'
+                    : image.fileName;
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n(
+                        'Are you sure you want to delete "{shortenedFileName}"?',
+                        {
+                            shortenedFileName: shortenedFileName
+                        }
+                    ),
+                    onConfirmed: () =>
+                        ImageHelper.deleteImage(dispatch, {
+                            softwareProductId,
+                            componentId,
+                            version,
+                            imageId: image.id
+                        })
+                }
+            });
+        },
+        onEditImageClick: (image, isReadOnlyMode) => {
+            SoftwareProductComponentsImagesActionHelper.openEditImageEditor(
+                dispatch,
+                {
+                    image,
+                    isReadOnlyMode,
+                    softwareProductId,
+                    componentId,
+                    version,
+                    modalClassName: 'image-modal-edit'
+                }
+            );
+        },
+        onSubmit: qdata => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    vspComponentId: componentId,
+                    version,
+                    qdata
+                }
+            );
+        }
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsImageListView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsImageListView);
index 5dd2fb6..a7c1bfa 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+import { actionTypes } from './SoftwareProductComponentsImageConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-
-               case actionTypes.IMAGES_LIST_UPDATE:
-                       return [...action.response];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.IMAGES_LIST_UPDATE:
+            return [...action.response];
+        default:
+            return state;
+    }
 };
index 004cbeb..cb67856 100644 (file)
@@ -20,113 +20,152 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
-import Input from'nfvo-components/input/validation/Input.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
 
 class SoftwareProductComponentsImageListView extends React.Component {
-       state = {
-               localFilter: ''
-       };
+    state = {
+        localFilter: ''
+    };
 
-       render() {
-               let {dataMap, onQDataChanged, isReadOnlyMode, qgenericFieldInfo} = this.props;
-               return(
-                       <div className='vsp-components-image'>
-                               <div className='image-data'>
-                                       <div>
-                                               { qgenericFieldInfo && <Form
-                                                       formReady={null}
-                                                       isValid={true}
-                                                       onSubmit={() => this.save()}
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       hasButtons={false}>
-
-                                                       <h3 className='section-title'>{i18n('Image')}</h3>
-                                                       <div className='rows-section'>
-                                                               <div className='row-flex-components'>
-                                                                       <div className='single-col'>
-                                                                               <Input
-                                                                                       data-test-id='providedBy'
-                                                                                       label={i18n('Image provided by')}
-                                                                                       type='select'
-                                                                                       isValid={qgenericFieldInfo['general/image/providedBy'].isValid}
-                                                                                       errorText={qgenericFieldInfo['general/image/providedBy'].errorText}
-                                                                                       value={dataMap['general/image/providedBy']}
-                                                                                       onChange={(e) => {
-                                                                                               const selectedIndex = e.target.selectedIndex;
-                                                                                               const val = e.target.options[selectedIndex].value;
-                                                                                               onQDataChanged({'general/image/providedBy' : val});}
-                                                                                       }>
-                                                                                       <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                                                                       { qgenericFieldInfo['general/image/providedBy'].enum.map(proto =>
-                                                                                               <option value={proto.enum} key={proto.enum}>{proto.title}</option>) }
-                                                                               </Input>
-                                                                       </div>
-                                                                       <div className='empty-two-col' />
-                                                               </div>
-                                                       </div>
-
-                                               </Form> }
-                                       </div>
-                               </div>
-                   {this.renderImagesList()}
+    render() {
+        let {
+            dataMap,
+            onQDataChanged,
+            isReadOnlyMode,
+            qgenericFieldInfo
+        } = this.props;
+        return (
+            <div className="vsp-components-image">
+                <div className="image-data">
+                    <div>
+                        {qgenericFieldInfo && (
+                            <Form
+                                formReady={null}
+                                isValid={true}
+                                onSubmit={() => this.save()}
+                                isReadOnlyMode={isReadOnlyMode}
+                                hasButtons={false}>
+                                <h3 className="section-title">
+                                    {i18n('Image')}
+                                </h3>
+                                <div className="rows-section">
+                                    <div className="row-flex-components">
+                                        <div className="single-col">
+                                            <Input
+                                                data-test-id="providedBy"
+                                                label={i18n(
+                                                    'Image provided by'
+                                                )}
+                                                type="select"
+                                                isValid={
+                                                    qgenericFieldInfo[
+                                                        'general/image/providedBy'
+                                                    ].isValid
+                                                }
+                                                errorText={
+                                                    qgenericFieldInfo[
+                                                        'general/image/providedBy'
+                                                    ].errorText
+                                                }
+                                                value={
+                                                    dataMap[
+                                                        'general/image/providedBy'
+                                                    ]
+                                                }
+                                                onChange={e => {
+                                                    const selectedIndex =
+                                                        e.target.selectedIndex;
+                                                    const val =
+                                                        e.target.options[
+                                                            selectedIndex
+                                                        ].value;
+                                                    onQDataChanged({
+                                                        'general/image/providedBy': val
+                                                    });
+                                                }}>
+                                                <option
+                                                    key="placeholder"
+                                                    value="">
+                                                    {i18n('Select...')}
+                                                </option>
+                                                {qgenericFieldInfo[
+                                                    'general/image/providedBy'
+                                                ].enum.map(proto => (
+                                                    <option
+                                                        value={proto.enum}
+                                                        key={proto.enum}>
+                                                        {proto.title}
+                                                    </option>
+                                                ))}
+                                            </Input>
+                                        </div>
+                                        <div className="empty-two-col" />
+                                    </div>
+                                </div>
+                            </Form>
+                        )}
+                    </div>
+                </div>
+                {this.renderImagesList()}
             </div>
-               );
-       };
-
-       renderImagesList() {
-               const {localFilter} = this.state;
-               let {isReadOnlyMode, onAddImage, isManual} = this.props;
-
-               return (
-                       <ListEditorView
-                               title={i18n('Images')}
-                               filterValue={localFilter}
-                               placeholder={i18n('Filter Images by Name')}
-                               isReadOnlyMode={isReadOnlyMode}
-                               onFilter={value => this.setState({localFilter: value})}
-                               onAdd={isManual ? () => onAddImage(isReadOnlyMode) : null}
-                               plusButtonTitle={i18n('Add Image')}
-                               twoColumns>
-                               {this.filterList().map(image => this.renderImagesListItem(image, isReadOnlyMode))}
-                       </ListEditorView>
-               );
-       };
+        );
+    }
 
+    renderImagesList() {
+        const { localFilter } = this.state;
+        let { isReadOnlyMode, onAddImage, isManual } = this.props;
 
-       renderImagesListItem(image, isReadOnlyMode) {
-               let {id, fileName} = image;
-               let {onEditImageClick, isManual, onDeleteImage} =  this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               isReadOnlyMode={isReadOnlyMode}
-                               onSelect={() => onEditImageClick(image, isReadOnlyMode)}
-                               onDelete={isManual ? () => onDeleteImage(image) : null}>
+        return (
+            <ListEditorView
+                title={i18n('Images')}
+                filterValue={localFilter}
+                placeholder={i18n('Filter Images by Name')}
+                isReadOnlyMode={isReadOnlyMode}
+                onFilter={value => this.setState({ localFilter: value })}
+                onAdd={isManual ? () => onAddImage(isReadOnlyMode) : null}
+                plusButtonTitle={i18n('Add Image')}
+                twoColumns>
+                {this.filterList().map(image =>
+                    this.renderImagesListItem(image, isReadOnlyMode)
+                )}
+            </ListEditorView>
+        );
+    }
 
-                               <ListEditorItemViewField>
-                                       <div className='image-filename-cell'><span className='image-filename'>{fileName}</span></div>
-                               </ListEditorItemViewField>
-                       </ListEditorItemView>
-               );
-       }
+    renderImagesListItem(image, isReadOnlyMode) {
+        let { id, fileName } = image;
+        let { onEditImageClick, isManual, onDeleteImage } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                isReadOnlyMode={isReadOnlyMode}
+                onSelect={() => onEditImageClick(image, isReadOnlyMode)}
+                onDelete={isManual ? () => onDeleteImage(image) : null}>
+                <ListEditorItemViewField>
+                    <div className="image-filename-cell">
+                        <span className="image-filename">{fileName}</span>
+                    </div>
+                </ListEditorItemViewField>
+            </ListEditorItemView>
+        );
+    }
 
-       filterList() {
-               let {imagesList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return imagesList.filter(({fileName = ''}) => {
-                               return escape(fileName).match(filter);
-                       });
-               }
-               else {
-                       return imagesList;
-               }
-       }
+    filterList() {
+        let { imagesList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return imagesList.filter(({ fileName = '' }) => {
+                return escape(fileName).match(filter);
+            });
+        } else {
+            return imagesList;
+        }
+    }
 
-       save() {
-               let {onSubmit, qdata} = this.props;
-               return onSubmit(qdata);
-       }
+    save() {
+        let { onSubmit, qdata } = this.props;
+        return onSubmit(qdata);
+    }
 }
 export default SoftwareProductComponentsImageListView;
index 64367c0..ec173cd 100644 (file)
@@ -18,32 +18,64 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 
 import Format from './Format.jsx';
 import Version from './Version.jsx';
 
-const FileDetails = ({editingMode, fileName, onDataChanged, isManual, dataMap, onQDataChanged, genericFieldInfo, qgenericFieldInfo}) => {
-       let fileNameCols = (editingMode) ? 3 : 4;
-       return(
-               <GridSection hasLastColSset>
-                       <GridItem colSpan={fileNameCols} lastColInRow={!editingMode}>
-                               <Input
-                                       disabled={!isManual}
-                                       onChange={fileName => onDataChanged({fileName}, forms.IMAGE_EDIT_FORM)}
-                                       label={i18n('Image Name')}
-                                       data-test-id='image-filename'
-                                       value={fileName}
-                                       isValid={genericFieldInfo.fileName.isValid}
-                                       errorText={genericFieldInfo.fileName.errorText}
-                                       isRequired={true}
-                                       type='text'
-                                       className='image-filename'/>
-                       </GridItem>
-                       {!editingMode && <div className='note-text'>{i18n('After image creation you must go to Edit Image and add File Version')}</div>}
-                       {editingMode && <Version isManual={isManual} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>}
-                       {editingMode && <Format isManual={isManual} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>}
-               </GridSection>
-       );
+const FileDetails = ({
+    editingMode,
+    fileName,
+    onDataChanged,
+    isManual,
+    dataMap,
+    onQDataChanged,
+    genericFieldInfo,
+    qgenericFieldInfo
+}) => {
+    let fileNameCols = editingMode ? 3 : 4;
+    return (
+        <GridSection hasLastColSset>
+            <GridItem colSpan={fileNameCols} lastColInRow={!editingMode}>
+                <Input
+                    disabled={!isManual}
+                    onChange={fileName =>
+                        onDataChanged({ fileName }, forms.IMAGE_EDIT_FORM)
+                    }
+                    label={i18n('Image Name')}
+                    data-test-id="image-filename"
+                    value={fileName}
+                    isValid={genericFieldInfo.fileName.isValid}
+                    errorText={genericFieldInfo.fileName.errorText}
+                    isRequired={true}
+                    type="text"
+                    className="image-filename"
+                />
+            </GridItem>
+            {!editingMode && (
+                <div className="note-text">
+                    {i18n(
+                        'After image creation you must go to Edit Image and add File Version'
+                    )}
+                </div>
+            )}
+            {editingMode && (
+                <Version
+                    isManual={isManual}
+                    dataMap={dataMap}
+                    qgenericFieldInfo={qgenericFieldInfo}
+                    onQDataChanged={onQDataChanged}
+                />
+            )}
+            {editingMode && (
+                <Format
+                    isManual={isManual}
+                    qgenericFieldInfo={qgenericFieldInfo}
+                    dataMap={dataMap}
+                    onQDataChanged={onQDataChanged}
+                />
+            )}
+        </GridSection>
+    );
 };
 export default FileDetails;
index 1f71c6b..0ee8fb7 100644 (file)
@@ -18,30 +18,34 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-
-const Format = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => {
-       return(
-               <GridItem colSpan={2}>
-                       <Input
-                               disabled={!isManual}
-                               data-test-id='image-format'
-                               type='select'
-                               label={i18n('Format')}
-                               className='input-options-select'
-                               groupClassName='bootstrap-input-options'
-                               isValid={qgenericFieldInfo['format'].isValid}
-                               errorText={qgenericFieldInfo['format'].errorText}
-                               value={dataMap['format']}
-                               onChange={(e) => {
-                                       const selectedIndex = e.target.selectedIndex;
-                                       const val = e.target.options[selectedIndex].value;
-                                       onQDataChanged({'format' : val});}
-                               }>
-                               <option key='placeholder' value=''>{i18n('Select...')}</option>
-                               {qgenericFieldInfo['format'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
-                       </Input>
-               </GridItem>
-       );
+const Format = ({ isManual, dataMap, qgenericFieldInfo, onQDataChanged }) => {
+    return (
+        <GridItem colSpan={2}>
+            <Input
+                disabled={!isManual}
+                data-test-id="image-format"
+                type="select"
+                label={i18n('Format')}
+                className="input-options-select"
+                groupClassName="bootstrap-input-options"
+                isValid={qgenericFieldInfo['format'].isValid}
+                errorText={qgenericFieldInfo['format'].errorText}
+                value={dataMap['format']}
+                onChange={e => {
+                    const selectedIndex = e.target.selectedIndex;
+                    const val = e.target.options[selectedIndex].value;
+                    onQDataChanged({ format: val });
+                }}>
+                <option key="placeholder" value="">
+                    {i18n('Select...')}
+                </option>
+                {qgenericFieldInfo['format'].enum.map(hv => (
+                    <option value={hv.enum} key={hv.enum}>
+                        {hv.title}
+                    </option>
+                ))}
+            </Input>
+        </GridItem>
+    );
 };
 export default Format;
-
index 24e54bb..ccf94bc 100644 (file)
@@ -19,21 +19,22 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const ImageDetails = ({dataMap, qgenericFieldInfo, onQDataChanged}) => {
-       return(
-               <GridSection title={i18n('Image Details')}>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       data-test-id='image-md5'
-                                       className='image-md5'
-                                       type='text'
-                                       label={i18n('md5')}
-                                       onChange={(md5) => onQDataChanged({'md5' : md5})}
-                                       isValid={qgenericFieldInfo['md5'].isValid}
-                                       errorText={qgenericFieldInfo['md5'].errorText}
-                                       value={dataMap['md5']}/>
-                       </GridItem>
-               </GridSection>
-       );
+const ImageDetails = ({ dataMap, qgenericFieldInfo, onQDataChanged }) => {
+    return (
+        <GridSection title={i18n('Image Details')}>
+            <GridItem colSpan={2}>
+                <Input
+                    data-test-id="image-md5"
+                    className="image-md5"
+                    type="text"
+                    label={i18n('md5')}
+                    onChange={md5 => onQDataChanged({ md5: md5 })}
+                    isValid={qgenericFieldInfo['md5'].isValid}
+                    errorText={qgenericFieldInfo['md5'].errorText}
+                    value={dataMap['md5']}
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 export default ImageDetails;
index bd55c5b..60454c5 100644 (file)
@@ -17,25 +17,29 @@ import React from 'react';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
-import {imageCustomValidations} from '../ImageValidations.js';
+import { imageCustomValidations } from '../ImageValidations.js';
 
-
-const Version = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => {
-       return(
-               <GridItem colSpan={1} lastColInRow>
-                       <Input
-                               disabled={!isManual}
-                               data-test-id='image-version'
-                               type='text'
-                               className='image-version'
-                               label={i18n('Version')}
-                               isRequired={true}
-                               onChange={(version) => onQDataChanged({'version' : version}, {'version' : imageCustomValidations['version']})}
-                               isValid={qgenericFieldInfo['version'].isValid}
-                               errorText={qgenericFieldInfo['version'].errorText}
-                               value={dataMap['version']}/>
-               </GridItem>
-       );
+const Version = ({ isManual, dataMap, qgenericFieldInfo, onQDataChanged }) => {
+    return (
+        <GridItem colSpan={1} lastColInRow>
+            <Input
+                disabled={!isManual}
+                data-test-id="image-version"
+                type="text"
+                className="image-version"
+                label={i18n('Version')}
+                isRequired={true}
+                onChange={version =>
+                    onQDataChanged(
+                        { version: version },
+                        { version: imageCustomValidations['version'] }
+                    )
+                }
+                isValid={qgenericFieldInfo['version'].isValid}
+                errorText={qgenericFieldInfo['version'].errorText}
+                value={dataMap['version']}
+            />
+        </GridItem>
+    );
 };
 export default Version;
-
index 350e80c..da8b73f 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentLoadBalancingView from './SoftwareProductComponentLoadBalancingRefView.jsx';
 import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 
-export const mapStateToProps = ({softwareProduct: {softwareProductComponents}}) => {
-
-       let {componentEditor: {qdata, qgenericFieldInfo: genericFieldInfo, dataMap}} = softwareProductComponents;
-
-       return {
-               qdata,
-               genericFieldInfo,
-               dataMap
-       };
+export const mapStateToProps = ({
+    softwareProduct: { softwareProductComponents }
+}) => {
+    let {
+        componentEditor: { qdata, qgenericFieldInfo: genericFieldInfo, dataMap }
+    } = softwareProductComponents;
 
+    return {
+        qdata,
+        genericFieldInfo,
+        dataMap
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
-       return {
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
-               onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});}
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onSubmit: ({ qdata }) => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    vspComponentId: componentId,
+                    qdata
+                }
+            );
+        }
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentLoadBalancingView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentLoadBalancingView);
index 1cbb9af..4c90fc0 100644 (file)
@@ -19,7 +19,7 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 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 Input from 'nfvo-components/input/validation/Input.jsx';
 
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
@@ -27,145 +27,244 @@ import GridItem from 'nfvo-components/grid/GridItem.jsx';
 const prefix = 'highAvailabilityAndLoadBalancing/';
 
 const pointers = [
-       {
-               key: 'failureLoadDistribution',
-               description: 'How is load distributed across live vms in the event of a vm/host failure? please describe'
-       },
-       {
-               key: 'nkModelImplementation',
-               description: 'Does each VM implement the N+K model for redundancy and failure protection? Please describe.'
-       },
-       {
-               key: 'architectureChoice',
-               description: 'What architecture is being implemented: ACTIVE-ACTIVE and/or ACTIVE-PASSIVE. ',
-               added: 'Will the arrangement be 1-1 or N-M? Please describe.'
-       },
-       {key: 'slaRequirements', description: 'Specify application SLA requirements on Cloud platform.'},
-       {
-               key: 'horizontalScaling',
-               description: 'Is horizontal scaling the preferred solution for HA and resiliency? Please describe.'
-       },
-       {
-               key: 'loadDistributionMechanism',
-               description: 'Can load be distributed across VMs? If so, are special mechanisms needed to re-balance data across VMs?',
-               added: 'Please describe.'
-       }
+    {
+        key: 'failureLoadDistribution',
+        description:
+            'How is load distributed across live vms in the event of a vm/host failure? please describe'
+    },
+    {
+        key: 'nkModelImplementation',
+        description:
+            'Does each VM implement the N+K model for redundancy and failure protection? Please describe.'
+    },
+    {
+        key: 'architectureChoice',
+        description:
+            'What architecture is being implemented: ACTIVE-ACTIVE and/or ACTIVE-PASSIVE. ',
+        added: 'Will the arrangement be 1-1 or N-M? Please describe.'
+    },
+    {
+        key: 'slaRequirements',
+        description: 'Specify application SLA requirements on Cloud platform.'
+    },
+    {
+        key: 'horizontalScaling',
+        description:
+            'Is horizontal scaling the preferred solution for HA and resiliency? Please describe.'
+    },
+    {
+        key: 'loadDistributionMechanism',
+        description:
+            'Can load be distributed across VMs? If so, are special mechanisms needed to re-balance data across VMs?',
+        added: 'Please describe.'
+    }
 ];
 //TODO check for buttons
 
-const TextAreaItem = ({item, toggle, expanded, genericFieldInfo, dataMap, onQDataChanged}) => (
-               <GridItem colSpan={3} key={item.key} >
-                       <div className={expanded ? 'title' : 'title add-padding'}
-                                data-test-id={`btn-${item.key}`}
-                                onClick={() => toggle(item.key)}>
-                                       <SVGIcon name={expanded ? 'chevronUp' : 'chevronDown'}/>
-                                       <span className='title-text'>{i18n(item.description)}</span>
-                                       {item.added && <div className='new-line'>{i18n(item.added)}</div>}
-                       </div>
-                       <div className={expanded ? 'collapse in' : 'collapse'}>
-                               <div>
-                                       <div>
-                                               <Input
-                                                       data-test-id={`input-${item.key}`}
-                                                       type='textarea'
-                                                       isValid={genericFieldInfo[`${prefix}${item.key}`].isValid}
-                                                       errorText={genericFieldInfo[`${prefix}${item.key}`].errorText}
-                                                       value={dataMap[`${prefix}${item.key}`]}
-                                                       onChange={(val) => onQDataChanged({[`${prefix}${item.key}`] : val})} />
-                                       </div>
-                               </div>
-                       </div>
-               </GridItem>
+const TextAreaItem = ({
+    item,
+    toggle,
+    expanded,
+    genericFieldInfo,
+    dataMap,
+    onQDataChanged
+}) => (
+    <GridItem colSpan={3} key={item.key}>
+        <div
+            className={expanded ? 'title' : 'title add-padding'}
+            data-test-id={`btn-${item.key}`}
+            onClick={() => toggle(item.key)}>
+            <SVGIcon name={expanded ? 'chevronUp' : 'chevronDown'} />
+            <span className="title-text">{i18n(item.description)}</span>
+            {item.added && <div className="new-line">{i18n(item.added)}</div>}
+        </div>
+        <div className={expanded ? 'collapse in' : 'collapse'}>
+            <div>
+                <div>
+                    <Input
+                        data-test-id={`input-${item.key}`}
+                        type="textarea"
+                        isValid={
+                            genericFieldInfo[`${prefix}${item.key}`].isValid
+                        }
+                        errorText={
+                            genericFieldInfo[`${prefix}${item.key}`].errorText
+                        }
+                        value={dataMap[`${prefix}${item.key}`]}
+                        onChange={val =>
+                            onQDataChanged({ [`${prefix}${item.key}`]: val })
+                        }
+                    />
+                </div>
+            </div>
+        </div>
+    </GridItem>
 );
 
 class SoftwareProductComponentLoadBalancingView extends React.Component {
-       static propTypes = {
-               componentId: PropTypes.string.isRequired,
-               softwareProductId: PropTypes.string.isRequired,
-               qdata: PropTypes.object,
-               qschema: PropTypes.object,
-               currentSoftwareProduct: PropTypes.object
-       };
+    static propTypes = {
+        componentId: PropTypes.string.isRequired,
+        softwareProductId: PropTypes.string.isRequired,
+        qdata: PropTypes.object,
+        qschema: PropTypes.object,
+        currentSoftwareProduct: PropTypes.object
+    };
 
-       state = {
-               expanded: {}
-       };
+    state = {
+        expanded: {}
+    };
 
-       render() {
-               let {dataMap, genericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props;
-               return (
-                       <div className='vsp-components-load-balancing'>
-                               <div className='halb-data'>
-                                       { genericFieldInfo && <Form
-                                               formReady={null}
-                                               isValid={true}
-                                               onSubmit={() => this.save()}
-                                               isReadOnlyMode={isReadOnlyMode}
-                                               hasButtons={false}>
-                                               <GridSection title={i18n('High Availability & Load Balancing')}>
-                                                       <GridItem colSpan={1}>
-                                                               <Input
-                                                                       data-test-id='input-is-component-mandatory'
-                                                                       label={i18n('Is Component Mandatory')}
-                                                                       type='select'
-                                                                       className='input-options-select'
-                                                                       groupClassName='bootstrap-input-options'
-                                                                       isValid={genericFieldInfo[`${prefix}isComponentMandatory`].isValid}
-                                                                       errorText={genericFieldInfo[`${prefix}isComponentMandatory`].errorText}
-                                                                       value={dataMap[`${prefix}isComponentMandatory`]}
-                                                                       onChange={(e) => {
-                                                                               const selectedIndex = e.target.selectedIndex;
-                                                                               const val = e.target.options[selectedIndex].value;
-                                                                               onQDataChanged({[`${prefix}isComponentMandatory`] : val});}
-                                                                       }>
-                                                                        <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                                                       { genericFieldInfo[`${prefix}isComponentMandatory`].enum.map(isMan => <option value={isMan.enum} key={isMan.enum}>{isMan.title}</option>) }
-                                                               </Input>
-                                                       </GridItem>
-                                                       <GridItem colSpan={3}/>
-                                                       <GridItem colSpan={1}>
-                                                               <Input
-                                                                       data-test-id='input-high-availability-mode'
-                                                                       label={i18n('High Availability Mode')}
-                                                                       type='select'
-                                                                       className='input-options-select'
-                                                                       groupClassName='bootstrap-input-options'
-                                                                       isValid={genericFieldInfo[`${prefix}highAvailabilityMode`].isValid}
-                                                                       errorText={genericFieldInfo[`${prefix}highAvailabilityMode`].errorText}
-                                                                       value={dataMap[`${prefix}highAvailabilityMode`]}
-                                                                       onChange={(e) => {
-                                                                               const selectedIndex = e.target.selectedIndex;
-                                                                               const val = e.target.options[selectedIndex].value;
-                                                                               onQDataChanged({[`${prefix}highAvailabilityMode`] : val});}
-                                                                       }>
-                                                                       <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                                                       {genericFieldInfo[`${prefix}highAvailabilityMode`].enum.map(hmode => <option value={hmode.enum} key={hmode.enum}>{hmode.title}</option>)}
-                                                               </Input>
-                                                       </GridItem>
-                                                       <GridItem colSpan={3}/>
-                                               </GridSection>
-                                               <GridSection>
-                                               {pointers.map(pointer => <TextAreaItem onQDataChanged={onQDataChanged}
-                                                          genericFieldInfo={genericFieldInfo} dataMap={dataMap} item={pointer} key={pointer.key + 'pKey'}
-                                                          expanded={this.state.expanded[pointer.key]} toggle={(name)=>{this.toggle(name);}} />)}
-                                               </GridSection>
-                                       </Form> }
-                               </div>
-                       </div>
-               );
-       }
+    render() {
+        let {
+            dataMap,
+            genericFieldInfo,
+            onQDataChanged,
+            isReadOnlyMode
+        } = this.props;
+        return (
+            <div className="vsp-components-load-balancing">
+                <div className="halb-data">
+                    {genericFieldInfo && (
+                        <Form
+                            formReady={null}
+                            isValid={true}
+                            onSubmit={() => this.save()}
+                            isReadOnlyMode={isReadOnlyMode}
+                            hasButtons={false}>
+                            <GridSection
+                                title={i18n(
+                                    'High Availability & Load Balancing'
+                                )}>
+                                <GridItem colSpan={1}>
+                                    <Input
+                                        data-test-id="input-is-component-mandatory"
+                                        label={i18n('Is Component Mandatory')}
+                                        type="select"
+                                        className="input-options-select"
+                                        groupClassName="bootstrap-input-options"
+                                        isValid={
+                                            genericFieldInfo[
+                                                `${prefix}isComponentMandatory`
+                                            ].isValid
+                                        }
+                                        errorText={
+                                            genericFieldInfo[
+                                                `${prefix}isComponentMandatory`
+                                            ].errorText
+                                        }
+                                        value={
+                                            dataMap[
+                                                `${prefix}isComponentMandatory`
+                                            ]
+                                        }
+                                        onChange={e => {
+                                            const selectedIndex =
+                                                e.target.selectedIndex;
+                                            const val =
+                                                e.target.options[selectedIndex]
+                                                    .value;
+                                            onQDataChanged({
+                                                [`${prefix}isComponentMandatory`]: val
+                                            });
+                                        }}>
+                                        <option key="placeholder" value="">
+                                            {i18n('Select...')}
+                                        </option>
+                                        {genericFieldInfo[
+                                            `${prefix}isComponentMandatory`
+                                        ].enum.map(isMan => (
+                                            <option
+                                                value={isMan.enum}
+                                                key={isMan.enum}>
+                                                {isMan.title}
+                                            </option>
+                                        ))}
+                                    </Input>
+                                </GridItem>
+                                <GridItem colSpan={3} />
+                                <GridItem colSpan={1}>
+                                    <Input
+                                        data-test-id="input-high-availability-mode"
+                                        label={i18n('High Availability Mode')}
+                                        type="select"
+                                        className="input-options-select"
+                                        groupClassName="bootstrap-input-options"
+                                        isValid={
+                                            genericFieldInfo[
+                                                `${prefix}highAvailabilityMode`
+                                            ].isValid
+                                        }
+                                        errorText={
+                                            genericFieldInfo[
+                                                `${prefix}highAvailabilityMode`
+                                            ].errorText
+                                        }
+                                        value={
+                                            dataMap[
+                                                `${prefix}highAvailabilityMode`
+                                            ]
+                                        }
+                                        onChange={e => {
+                                            const selectedIndex =
+                                                e.target.selectedIndex;
+                                            const val =
+                                                e.target.options[selectedIndex]
+                                                    .value;
+                                            onQDataChanged({
+                                                [`${prefix}highAvailabilityMode`]: val
+                                            });
+                                        }}>
+                                        <option key="placeholder" value="">
+                                            {i18n('Select...')}
+                                        </option>
+                                        {genericFieldInfo[
+                                            `${prefix}highAvailabilityMode`
+                                        ].enum.map(hmode => (
+                                            <option
+                                                value={hmode.enum}
+                                                key={hmode.enum}>
+                                                {hmode.title}
+                                            </option>
+                                        ))}
+                                    </Input>
+                                </GridItem>
+                                <GridItem colSpan={3} />
+                            </GridSection>
+                            <GridSection>
+                                {pointers.map(pointer => (
+                                    <TextAreaItem
+                                        onQDataChanged={onQDataChanged}
+                                        genericFieldInfo={genericFieldInfo}
+                                        dataMap={dataMap}
+                                        item={pointer}
+                                        key={pointer.key + 'pKey'}
+                                        expanded={
+                                            this.state.expanded[pointer.key]
+                                        }
+                                        toggle={name => {
+                                            this.toggle(name);
+                                        }}
+                                    />
+                                ))}
+                            </GridSection>
+                        </Form>
+                    )}
+                </div>
+            </div>
+        );
+    }
 
-       toggle(name) {
-               let st = this.state.expanded[name] ? true : false;
-               let newState = {...this.state};
-               newState.expanded[name] = !st;
-               this.setState(newState);
-       }
+    toggle(name) {
+        let st = this.state.expanded[name] ? true : false;
+        let newState = { ...this.state };
+        newState.expanded[name] = !st;
+        this.setState(newState);
+    }
 
-       save() {
-               let {onSubmit, qdata} = this.props;
-               return onSubmit({qdata});
-       }
+    save() {
+        let { onSubmit, qdata } = this.props;
+        return onSubmit({ qdata });
+    }
 }
 
 export default SoftwareProductComponentLoadBalancingView;
index 8871aab..0b0b9ae 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentsMonitoringView from './SoftwareProductComponentsMonitoringView.jsx';
 import SoftwareProductComponentsMonitoringAction from './SoftwareProductComponentsMonitoringActionHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-
-
-export const mapStateToProps = ({softwareProduct}) => {
-
-       let {softwareProductComponents: {monitoring}} = softwareProduct;
-       return {
-               filenames: monitoring
-       };
-
+export const mapStateToProps = ({ softwareProduct }) => {
+    let { softwareProductComponents: { monitoring } } = softwareProduct;
+    return {
+        filenames: monitoring
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
-
-       return {
-               onDropMibFileToUpload: (formData, type) =>
-                       SoftwareProductComponentsMonitoringAction.uploadFile(dispatch, {
-                               softwareProductId,
-                               version,
-                               componentId,
-                               formData,
-                               type
-                       }),
-
-               onDeleteFile: type => SoftwareProductComponentsMonitoringAction.deleteFile(dispatch, {
-                       softwareProductId,
-                       version,
-                       componentId,
-                       type
-               }),
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onDropMibFileToUpload: (formData, type) =>
+            SoftwareProductComponentsMonitoringAction.uploadFile(dispatch, {
+                softwareProductId,
+                version,
+                componentId,
+                formData,
+                type
+            }),
 
-               onFileUploadError: () => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                       data: {
-                               title: i18n('Upload Failed'),
-                               msg: i18n('Expected "zip" file. Please check the provided file type.')
-                       }
-               })
-       };
+        onDeleteFile: type =>
+            SoftwareProductComponentsMonitoringAction.deleteFile(dispatch, {
+                softwareProductId,
+                version,
+                componentId,
+                type
+            }),
 
+        onFileUploadError: () =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                data: {
+                    title: i18n('Upload Failed'),
+                    msg: i18n(
+                        'Expected "zip" file. Please check the provided file type.'
+                    )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsMonitoringView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsMonitoringView);
index 3db708b..c60bc5f 100644 (file)
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes } from './SoftwareProductComponentsMonitoringConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 function baseUrl(vspId, version, componentId) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/uploads`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/uploads`;
 }
 
-let onInvalidFileSizeUpload = (dispatch) => dispatch({
-       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-       data: {
-               title: i18n('Upload Failed'),
-               msg: i18n('no zip file was uploaded or zip file doesn\'t exist')
-       }
-});
+let onInvalidFileSizeUpload = dispatch =>
+    dispatch({
+        type: modalActionTypes.GLOBAL_MODAL_ERROR,
+        data: {
+            title: i18n('Upload Failed'),
+            msg: i18n("no zip file was uploaded or zip file doesn't exist")
+        }
+    });
 
-let uploadFile = (dispatch, {softwareProductId, version, componentId, formData, type}) => {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`, formData).then(()=> dispatch({
-               type: actionTypes.MONITOR_UPLOADED, data: {filename: formData.get('upload').name, type : type}
-       }));
+let uploadFile = (
+    dispatch,
+    { softwareProductId, version, componentId, formData, type }
+) => {
+    return RestAPIUtil.post(
+        `${baseUrl(softwareProductId, version, componentId)}/types/${type}`,
+        formData
+    ).then(() =>
+        dispatch({
+            type: actionTypes.MONITOR_UPLOADED,
+            data: { filename: formData.get('upload').name, type: type }
+        })
+    );
 };
 
-let deleteFile = (dispatch, {softwareProductId, version, componentId, type}) => {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`).then(()=> dispatch({
-               type: actionTypes.MONITOR_DELETED,
-               data : { type: type}
-       }));
+let deleteFile = (
+    dispatch,
+    { softwareProductId, version, componentId, type }
+) => {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version, componentId)}/types/${type}`
+    ).then(() =>
+        dispatch({
+            type: actionTypes.MONITOR_DELETED,
+            data: { type: type }
+        })
+    );
 };
 
-
 const SoftwareProductComponentsMonitoringAction = {
+    fetchExistingFiles(dispatch, { softwareProductId, version, componentId }) {
+        return RestAPIUtil.fetch(
+            `${baseUrl(softwareProductId, version, componentId)}`
+        ).then(response =>
+            dispatch({
+                type: actionTypes.MONITOR_FILES_DATA_CHANGE,
+                data: response
+            })
+        );
+    },
 
-       fetchExistingFiles(dispatch, {softwareProductId, version, componentId}){
-               return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`).then(response =>
-                       dispatch({
-                               type: actionTypes.MONITOR_FILES_DATA_CHANGE,
-                               data: response
-                       })
-               );
-       },
-
-       uploadFile(dispatch, {softwareProductId, version, componentId, formData, type}){
-               if (formData.get('upload').size) {
-                       return uploadFile(dispatch, {softwareProductId, version, componentId, formData, type});
-               }
-               else {
-                       onInvalidFileSizeUpload(dispatch);
-               }
-       },
-
-       deleteFile(dispatch, {softwareProductId, version, componentId, type}){
-               return deleteFile(dispatch, {softwareProductId, version, componentId, type});
-       }
+    uploadFile(
+        dispatch,
+        { softwareProductId, version, componentId, formData, type }
+    ) {
+        if (formData.get('upload').size) {
+            return uploadFile(dispatch, {
+                softwareProductId,
+                version,
+                componentId,
+                formData,
+                type
+            });
+        } else {
+            onInvalidFileSizeUpload(dispatch);
+        }
+    },
 
+    deleteFile(dispatch, { softwareProductId, version, componentId, type }) {
+        return deleteFile(dispatch, {
+            softwareProductId,
+            version,
+            componentId,
+            type
+        });
+    }
 };
 
 export default SoftwareProductComponentsMonitoringAction;
index bf2cbd2..10049d6 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-
 export const actionTypes = keyMirror({
-       MONITOR_FILES_DATA_CHANGE: null,
-       MONITOR_UPLOADED: null,
-       MONITOR_DELETED: null
+    MONITOR_FILES_DATA_CHANGE: null,
+    MONITOR_UPLOADED: null,
+    MONITOR_DELETED: null
 });
 
 export const fileTypes = {
-       SNMP_TRAP: 'SNMP_TRAP',
-       SNMP_POLL: 'SNMP_POLL',
-       VES_EVENT: 'VES_EVENTS'
+    SNMP_TRAP: 'SNMP_TRAP',
+    SNMP_POLL: 'SNMP_POLL',
+    VES_EVENT: 'VES_EVENTS'
 };
 
 export const type2Name = {
-       SNMP_TRAP: 'snmpTrap',
-       SNMP_POLL: 'snmpPoll',
-       VES_EVENTS: 'vesEvent'
+    SNMP_TRAP: 'snmpTrap',
+    SNMP_POLL: 'snmpPoll',
+    VES_EVENTS: 'vesEvent'
 };
 
-
 export const type2Title = {
-       SNMP_TRAP : i18n('SNMP Trap'),
-       SNMP_POLL : i18n('SNMP Poll'),
-       VES_EVENTS: i18n('VES')
+    SNMP_TRAP: i18n('SNMP Trap'),
+    SNMP_POLL: i18n('SNMP Poll'),
+    VES_EVENTS: i18n('VES')
 };
-
index f5cfe6f..61ad4ec 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, type2Name} from './SoftwareProductComponentsMonitoringConstants.js';
+import {
+    actionTypes,
+    type2Name
+} from './SoftwareProductComponentsMonitoringConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.MONITOR_FILES_DATA_CHANGE:
-                       return action.data;
-               case actionTypes.MONITOR_UPLOADED:
-                       return {
-                               ...state,
-                               [type2Name[action.data.type]]: action.data.filename
-                       };
-               case actionTypes.MONITOR_DELETED:
-                       return {
-                               ...state,
-                               [type2Name[action.data.type]]: undefined
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.MONITOR_FILES_DATA_CHANGE:
+            return action.data;
+        case actionTypes.MONITOR_UPLOADED:
+            return {
+                ...state,
+                [type2Name[action.data.type]]: action.data.filename
+            };
+        case actionTypes.MONITOR_DELETED:
+            return {
+                ...state,
+                [type2Name[action.data.type]]: undefined
+            };
+        default:
+            return state;
+    }
 };
index 95d1e4e..771bca1 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import Dropzone from 'react-dropzone';
 import Button from 'sdc-ui/lib/react/Button.js';
 import DraggableUploadFileBox from 'nfvo-components/fileupload/DraggableUploadFileBox.jsx';
-import {fileTypes, type2Title, type2Name} from './SoftwareProductComponentsMonitoringConstants.js';
-
-
+import {
+    fileTypes,
+    type2Title,
+    type2Name
+} from './SoftwareProductComponentsMonitoringConstants.js';
 
 class SoftwareProductComponentsMonitoringView extends Component {
-
-       static propTypes = {
-               isReadOnlyMode: PropTypes.bool,
-               filenames: PropTypes.object,
-               softwareProductId: PropTypes.string,
-
-               onDropMibFileToUpload: PropTypes.func,
-               onDeleteSnmpFile: PropTypes.func
-       };
-
-       state = {
-               dragging: false
-       };
-
-
-
-
-       render() {
-               return (
-                       <div className='vsp-component-monitoring'>
-                               {this.renderDropzoneWithType(fileTypes.VES_EVENT)}
-                               {this.renderDropzoneWithType(fileTypes.SNMP_TRAP)}
-                               {this.renderDropzoneWithType(fileTypes.SNMP_POLL)}
-                       </div>
-               );
-       }
-
-       renderDropzoneWithType(type) {
-               let {isReadOnlyMode, filenames} = this.props;
-               let fileByType = type2Name[type];
-               let fileName = (filenames) ? filenames[fileByType] : undefined;
-               let refAndName = `fileInput${type.toString()}`;
-               let typeDisplayName = type2Title[type];
-               return (
-                       <Dropzone
-                               className={`dropzone ${this.state.dragging ? 'active-dragging' : ''}`}
-                               onDrop={(acceptedFiles, rejectedFiles) => this.handleImport(acceptedFiles, rejectedFiles, {isReadOnlyMode, type, refAndName})}
-                               onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode)}
-                               onDragLeave={() => this.setState({dragging:false})}
-                               multiple={false}
-                               disableClick={true}
-                               ref={refAndName}
-                               name={refAndName}
-                               accept='.zip'>
-                               <div className='draggable-wrapper'>
-                                       <div className='section-title'>{typeDisplayName}</div>
-                                       {fileName ? this.renderUploadedFileName(fileName, type, isReadOnlyMode) : this.renderUploadButton(refAndName)}
-                               </div>
-                       </Dropzone>
-               );
-       }
-
-       renderUploadButton(refAndName) {
-               let {isReadOnlyMode} = this.props;
-               return (
-                       <DraggableUploadFileBox
-                               dataTestId={`monitoring-upload-${refAndName}`}
-                               className='software-product-landing-view-top-block-col-upl'
-                               isReadOnlyMode={isReadOnlyMode}
-                               onClick={() => this.refs[refAndName].open()}/>
-               );
-       }
-
-       renderUploadedFileName(filename, type, isReadOnlyMode) {
-               return (
-                               <div className='monitoring-file'>
-                                       <Button
-                                               color='white'
-                                               disabled={true}
-                                               className='filename'>
-                                               {filename}
-                                       </Button>
-
-                                       <Button
-                                               color='gray'
-                                               data-test-id={`monitoring-delete-${type}`}
-                                               disabled={isReadOnlyMode}
-                                               onClick={()=>this.props.onDeleteFile(type)}
-                                               iconName='close'
-                                               className='delete'/>
-                               </div>
-               );
-       }
-
-
-       handleOnDragEnter(isReadOnlyMode) {
-               if (!isReadOnlyMode) {
-                       this.setState({dragging: true});
-               }
-       }
-
-       handleImport(files, rejectedFiles, {isReadOnlyMode, type, refAndName}) {
-               if (isReadOnlyMode) {
-                       return;
-               }
-               if (files.length > 0) {
-                       this.setState({dragging: false});
-                       let file = files[0];
-                       let formData = new FormData();
-                       formData.append('upload', file);
-                       this.refs[refAndName].value = '';
-                       this.props.onDropMibFileToUpload(formData, type);
-               } else if (rejectedFiles.length > 0) {
-                       this.setState({dragging: false});
-                       this.props.onFileUploadError();
-               }
-       }
+    static propTypes = {
+        isReadOnlyMode: PropTypes.bool,
+        filenames: PropTypes.object,
+        softwareProductId: PropTypes.string,
+
+        onDropMibFileToUpload: PropTypes.func,
+        onDeleteSnmpFile: PropTypes.func
+    };
+
+    state = {
+        dragging: false
+    };
+
+    render() {
+        return (
+            <div className="vsp-component-monitoring">
+                {this.renderDropzoneWithType(fileTypes.VES_EVENT)}
+                {this.renderDropzoneWithType(fileTypes.SNMP_TRAP)}
+                {this.renderDropzoneWithType(fileTypes.SNMP_POLL)}
+            </div>
+        );
+    }
+
+    renderDropzoneWithType(type) {
+        let { isReadOnlyMode, filenames } = this.props;
+        let fileByType = type2Name[type];
+        let fileName = filenames ? filenames[fileByType] : undefined;
+        let refAndName = `fileInput${type.toString()}`;
+        let typeDisplayName = type2Title[type];
+        return (
+            <Dropzone
+                className={`dropzone ${
+                    this.state.dragging ? 'active-dragging' : ''
+                }`}
+                onDrop={(acceptedFiles, rejectedFiles) =>
+                    this.handleImport(acceptedFiles, rejectedFiles, {
+                        isReadOnlyMode,
+                        type,
+                        refAndName
+                    })
+                }
+                onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode)}
+                onDragLeave={() => this.setState({ dragging: false })}
+                multiple={false}
+                disableClick={true}
+                ref={refAndName}
+                name={refAndName}
+                accept=".zip">
+                <div className="draggable-wrapper">
+                    <div className="section-title">{typeDisplayName}</div>
+                    {fileName
+                        ? this.renderUploadedFileName(
+                              fileName,
+                              type,
+                              isReadOnlyMode
+                          )
+                        : this.renderUploadButton(refAndName)}
+                </div>
+            </Dropzone>
+        );
+    }
+
+    renderUploadButton(refAndName) {
+        let { isReadOnlyMode } = this.props;
+        return (
+            <DraggableUploadFileBox
+                dataTestId={`monitoring-upload-${refAndName}`}
+                className="software-product-landing-view-top-block-col-upl"
+                isReadOnlyMode={isReadOnlyMode}
+                onClick={() => this.refs[refAndName].open()}
+            />
+        );
+    }
+
+    renderUploadedFileName(filename, type, isReadOnlyMode) {
+        return (
+            <div className="monitoring-file">
+                <Button color="white" disabled={true} className="filename">
+                    {filename}
+                </Button>
+
+                <Button
+                    color="gray"
+                    data-test-id={`monitoring-delete-${type}`}
+                    disabled={isReadOnlyMode}
+                    onClick={() => this.props.onDeleteFile(type)}
+                    iconName="close"
+                    className="delete"
+                />
+            </div>
+        );
+    }
+
+    handleOnDragEnter(isReadOnlyMode) {
+        if (!isReadOnlyMode) {
+            this.setState({ dragging: true });
+        }
+    }
+
+    handleImport(files, rejectedFiles, { isReadOnlyMode, type, refAndName }) {
+        if (isReadOnlyMode) {
+            return;
+        }
+        if (files.length > 0) {
+            this.setState({ dragging: false });
+            let file = files[0];
+            let formData = new FormData();
+            formData.append('upload', file);
+            this.refs[refAndName].value = '';
+            this.props.onDropMibFileToUpload(formData, type);
+        } else if (rejectedFiles.length > 0) {
+            this.setState({ dragging: false });
+            this.props.onFileUploadError();
+        }
+    }
 }
 
 export default SoftwareProductComponentsMonitoringView;
index d4aaf7c..e705618 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import NICCreationActionHelper from './NICCreationActionHelper.js';
 import NICCreationView from './NICCreationView.jsx';
 import SoftwareProductComponentsNetworkActionHelper from '../SoftwareProductComponentsNetworkActionHelper.js';
-import {networkTypes, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js';
+import {
+    networkTypes,
+    NIC_CREATION_FORM_NAME
+} from '../SoftwareProductComponentsNetworkConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents} = softwareProduct;
-       let {network: {nicCreation = {}}} = softwareProductComponents;
-       let {data, genericFieldInfo, formReady} = nicCreation;
-       data = {...data, networkType: networkTypes.EXTERNAL};
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: { data: currentSoftwareProduct = {} },
+        softwareProductComponents
+    } = softwareProduct;
+    let { network: { nicCreation = {} } } = softwareProductComponents;
+    let { data, genericFieldInfo, formReady } = nicCreation;
+    data = { ...data, networkType: networkTypes.EXTERNAL };
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       return {
-               currentSoftwareProduct,
-               data,
-               genericFieldInfo,
-               isFormValid,
-               formReady
-       };
+    return {
+        currentSoftwareProduct,
+        data,
+        genericFieldInfo,
+        isFormValid,
+        formReady
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: NIC_CREATION_FORM_NAME}),
-               onCancel: () => NICCreationActionHelper.close(dispatch),
-               onSubmit: ({nic, componentId}) => {
-                       SoftwareProductComponentsNetworkActionHelper.createNIC(dispatch, {nic, softwareProductId, componentId, version});
-                       NICCreationActionHelper.close(dispatch);
-               },
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, NIC_CREATION_FORM_NAME)
-       };
+const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: NIC_CREATION_FORM_NAME
+            }),
+        onCancel: () => NICCreationActionHelper.close(dispatch),
+        onSubmit: ({ nic, componentId }) => {
+            SoftwareProductComponentsNetworkActionHelper.createNIC(dispatch, {
+                nic,
+                softwareProductId,
+                componentId,
+                version
+            });
+            NICCreationActionHelper.close(dispatch);
+        },
+        onValidateForm: () =>
+            ValidationHelper.validateForm(dispatch, NIC_CREATION_FORM_NAME)
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(NICCreationView);
index a40b32d..4f200ce 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from '../SoftwareProductComponentsNetworkConstants';
+import { actionTypes } from '../SoftwareProductComponentsNetworkConstants';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 
 export default {
+    open(
+        dispatch,
+        { softwareProductId, componentId, modalClassName, version }
+    ) {
+        dispatch({
+            type: actionTypes.NICCreation.OPEN
+        });
 
-       open(dispatch, {softwareProductId, componentId, modalClassName, version}) {
-               dispatch({
-                       type: actionTypes.NICCreation.OPEN
-               });
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName: modalContentMapper.NIC_CREATION,
+                title: i18n('Create NEW NIC'),
+                modalClassName,
+                modalComponentProps: { softwareProductId, componentId, version }
+            }
+        });
+    },
 
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.NIC_CREATION,
-                               title: i18n('Create NEW NIC'),
-                               modalClassName,
-                               modalComponentProps: {softwareProductId, componentId, version}
-                       }
-               });
-       },
-
-       close(dispatch){
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-               dispatch({
-                       type: actionTypes.NICCreation.CLEAR_DATA
-               });
-       }
+    close(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+        dispatch({
+            type: actionTypes.NICCreation.CLEAR_DATA
+        });
+    }
 };
index c7e2495..8309c40 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js';
+import {
+    actionTypes,
+    NIC_CREATION_FORM_NAME
+} from '../SoftwareProductComponentsNetworkConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.NICCreation.OPEN:
-                       return {
-                               ...state,
-                               data: {},
-                               formName: NIC_CREATION_FORM_NAME,
-                               formReady: null,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data : true}]
-                                       },
-                                       'networkDescription' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 50}]
-                                       }
-                               }
-                       };
-               case actionTypes.NICCreation.CLEAR_DATA:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.NICCreation.OPEN:
+            return {
+                ...state,
+                data: {},
+                formName: NIC_CREATION_FORM_NAME,
+                formReady: null,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    networkDescription: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 50 }]
+                    }
+                }
+            };
+        case actionTypes.NICCreation.CLEAR_DATA:
+            return {};
+        default:
+            return state;
+    }
 };
index 2588768..88525c0 100644 (file)
@@ -22,103 +22,136 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
 const NICPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       networkId: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    networkId: PropTypes.string
 });
 
 class NICCreationView extends React.Component {
+    static propTypes = {
+        data: NICPropType,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               data: NICPropType,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
+    render() {
+        let {
+            data = {},
+            onDataChanged,
+            genericFieldInfo,
+            isFormValid,
+            onValidateForm,
+            formReady
+        } = this.props;
+        let { name, description, networkDescription } = data;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref={form => (this.form = form)}
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        submitButtonText={
+                            data.id ? i18n('Save') : i18n('Create')
+                        }
+                        onReset={() => this.props.onCancel()}
+                        labledButtons={true}
+                        isValid={isFormValid}
+                        onValidateForm={() => onValidateForm()}
+                        formReady={formReady}>
+                        <GridSection hasLastColSet>
+                            <GridItem colSpan={4} lastColInRow>
+                                <Input
+                                    value={name}
+                                    label={i18n('Name')}
+                                    data-test-id="nic-name"
+                                    onChange={name => onDataChanged({ name })}
+                                    isRequired={true}
+                                    type="text"
+                                    isValid={genericFieldInfo['name'].isValid}
+                                    errorText={
+                                        genericFieldInfo['name'].errorText
+                                    }
+                                    className="field-section"
+                                />
+                                <Input
+                                    value={description}
+                                    label={i18n('Description')}
+                                    data-test-id="nic-description"
+                                    onChange={description =>
+                                        onDataChanged({ description })
+                                    }
+                                    isValid={
+                                        genericFieldInfo['description'].isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo['description']
+                                            .errorText
+                                    }
+                                    type="textarea"
+                                    className="field-section"
+                                />
+                            </GridItem>
+                        </GridSection>
+                        <GridSection title={i18n('Network')} hasLastColSet>
+                            <GridItem colSpan={2}>
+                                <div className="form-group">
+                                    <label className="control-label">
+                                        {i18n('Network Type')}
+                                    </label>
+                                    <div className="network-type-radio">
+                                        <Input
+                                            label={i18n('Internal')}
+                                            disabled
+                                            checked={false}
+                                            data-test-id="nic-internal"
+                                            className="network-radio disabled"
+                                            type="radio"
+                                        />
+                                        <Input
+                                            label={i18n('External')}
+                                            disabled
+                                            checked={true}
+                                            data-test-id="nic-external"
+                                            className="network-radio disabled"
+                                            type="radio"
+                                        />
+                                    </div>
+                                </div>
+                            </GridItem>
+                            <GridItem colSpan={2} lastColInRow>
+                                <Input
+                                    value={networkDescription}
+                                    label={i18n('Network Description')}
+                                    data-test-id="nic-network-description"
+                                    onChange={networkDescription =>
+                                        onDataChanged({ networkDescription })
+                                    }
+                                    isValid={
+                                        genericFieldInfo['networkDescription']
+                                            .isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo['networkDescription']
+                                            .errorText
+                                    }
+                                    type="text"
+                                    className="field-section"
+                                />
+                            </GridItem>
+                        </GridSection>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       render() {
-               let {data = {}, onDataChanged, genericFieldInfo, isFormValid, onValidateForm, formReady} = this.props;
-               let {name, description, networkDescription} = data;
-               return (
-                       <div>
-                       {genericFieldInfo && <Form
-                               ref={(form) => this.form = form}
-                               hasButtons={true}
-                               onSubmit={ () => this.submit() }
-                               submitButtonText={data.id ? i18n('Save') : i18n('Create')}
-                               onReset={ () => this.props.onCancel() }
-                               labledButtons={true}
-                               isValid={isFormValid}
-                               onValidateForm={() => onValidateForm()}
-                               formReady={formReady} >
-                               <GridSection hasLastColSet>
-                                       <GridItem colSpan={4} lastColInRow>
-                                               <Input
-                                                       value={name}
-                                                       label={i18n('Name')}
-                                                       data-test-id='nic-name'
-                                                       onChange={name => onDataChanged({name})}
-                                                       isRequired={true}
-                                                       type='text'
-                                                       isValid={genericFieldInfo['name'].isValid}
-                                                       errorText={genericFieldInfo['name'].errorText}
-                                                       className='field-section'/>
-                                               <Input
-                                                       value={description}
-                                                       label={i18n('Description')}
-                                                       data-test-id='nic-description'
-                                                       onChange={description => onDataChanged({description})}
-                                                       isValid={genericFieldInfo['description'].isValid}
-                                                       errorText={genericFieldInfo['description'].errorText}
-                                                       type='textarea'
-                                                       className='field-section'/>
-                                       </GridItem>
-                               </GridSection>
-                               <GridSection title={i18n('Network')} hasLastColSet>
-                                       <GridItem colSpan={2}>
-                                               <div className='form-group'>
-                                                       <label className='control-label'>{i18n('Network Type')}</label>
-                                                       <div className='network-type-radio'>
-                                                               <Input
-                                                                       label={i18n('Internal')}
-                                                                       disabled
-                                                                       checked={false}
-                                                                       data-test-id='nic-internal'
-                                                                       className='network-radio disabled'
-                                                                       type='radio'/>
-                                                               <Input
-                                                                       label={i18n('External')}
-                                                                       disabled
-                                                                       checked={true}
-                                                                       data-test-id='nic-external'
-                                                                       className='network-radio disabled'
-                                                                       type='radio'/>
-                                                       </div>
-                                               </div>
-                                       </GridItem>
-                                       <GridItem colSpan={2} lastColInRow>
-                                               <Input
-                                                       value={networkDescription}
-                                                       label={i18n('Network Description')}
-                                                       data-test-id='nic-network-description'
-                                                       onChange={networkDescription => onDataChanged({networkDescription})}
-                                                       isValid={genericFieldInfo['networkDescription'].isValid}
-                                                       errorText={genericFieldInfo['networkDescription'].errorText}
-                                                       type='text'
-                                                       className='field-section'/>
-                                       </GridItem>
-                               </GridSection>
-                       </Form>}
-                       </div>
-               );
-       }
-
-
-       submit() {
-               const {data: nic, componentId} = this.props;
-               this.props.onSubmit({nic, componentId});
-       }
+    submit() {
+        const { data: nic, componentId } = this.props;
+        this.props.onSubmit({ nic, componentId });
+    }
 }
 
 export default NICCreationView;
index 93bd0bd..d7205b4 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductComponentsNetworkActionHelper from './SoftwareProductComponentsNetworkActionHelper.js';
 import SoftwareProductComponentsNICEditorView from './SoftwareProductComponentsNICEditorView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
-import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
-import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
+import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js';
 
-export const mapStateToProps = ({softwareProduct, currentScreen}) => {
-
-       let {softwareProductEditor: {data:currentSoftwareProduct = {},  isValidityData = true}, softwareProductComponents} = softwareProduct;
-       let {network: {nicEditor = {}}} = softwareProductComponents;
-       let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = nicEditor;
-       let {props: {isReadOnlyMode}} = currentScreen;
-       let {onboardingMethod} = currentSoftwareProduct;
-       let protocols = [];
-       if(qdata && qdata.protocols && qdata.protocols.protocols && qdata.protocols.protocols.length){
-               protocols = qdata.protocols.protocols;
-       }
-       let {version} = currentSoftwareProduct;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo) &&  ValidationHelper.checkFormValid(qgenericFieldInfo);
-
-       return {
-               currentSoftwareProduct,
-               isValidityData,
-               version,
-               data,
-               qdata,
-               dataMap,
-               isFormValid,
-               formReady,
-               genericFieldInfo,
-               qgenericFieldInfo,
-               isReadOnlyMode,
-               protocols,
-               isManual: onboardingMethod === onboardingMethodTypes.MANUAL
-       };
+export const mapStateToProps = ({ softwareProduct, currentScreen }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct = {},
+            isValidityData = true
+        },
+        softwareProductComponents
+    } = softwareProduct;
+    let { network: { nicEditor = {} } } = softwareProductComponents;
+    let {
+        data,
+        qdata,
+        genericFieldInfo,
+        qgenericFieldInfo,
+        dataMap,
+        formReady
+    } = nicEditor;
+    let { props: { isReadOnlyMode } } = currentScreen;
+    let { onboardingMethod } = currentSoftwareProduct;
+    let protocols = [];
+    if (
+        qdata &&
+        qdata.protocols &&
+        qdata.protocols.protocols &&
+        qdata.protocols.protocols.length
+    ) {
+        protocols = qdata.protocols.protocols;
+    }
+    let { version } = currentSoftwareProduct;
+    let isFormValid =
+        ValidationHelper.checkFormValid(genericFieldInfo) &&
+        ValidationHelper.checkFormValid(qgenericFieldInfo);
 
+    return {
+        currentSoftwareProduct,
+        isValidityData,
+        version,
+        data,
+        qdata,
+        dataMap,
+        isFormValid,
+        formReady,
+        genericFieldInfo,
+        qgenericFieldInfo,
+        isReadOnlyMode,
+        protocols,
+        isManual: onboardingMethod === onboardingMethodTypes.MANUAL
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData,
-                       formName: forms.NIC_EDIT_FORM}),
-               onSubmit: ({data, qdata}) => SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}),
-               onCancel: () => SoftwareProductComponentsNetworkActionHelper.closeNICEditor(dispatch),
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, forms.NIC_EDIT_FORM),
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
-                       qName: NIC_QUESTIONNAIRE}),
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: forms.NIC_EDIT_FORM
+            }),
+        onSubmit: ({ data, qdata }) =>
+            SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire(
+                dispatch,
+                { softwareProductId, version, componentId, data, qdata }
+            ),
+        onCancel: () =>
+            SoftwareProductComponentsNetworkActionHelper.closeNICEditor(
+                dispatch
+            ),
+        onValidateForm: () =>
+            ValidationHelper.validateForm(dispatch, forms.NIC_EDIT_FORM),
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: NIC_QUESTIONNAIRE
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentsNICEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductComponentsNICEditorView
+);
index dd37135..2da9b4b 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.NICEditor.FILL_DATA:
-                       return {
-                               ...state,
-                               data: action.nic,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data : true}]
-                                       },
-                                       'networkDescription' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               },
-                               formName: forms.NIC_EDIT_FORM
-                       };
-               case actionTypes.NICEditor.CLEAR_DATA:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.NICEditor.FILL_DATA:
+            return {
+                ...state,
+                data: action.nic,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    networkDescription: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                },
+                formName: forms.NIC_EDIT_FORM
+            };
+        case actionTypes.NICEditor.CLEAR_DATA:
+            return {};
+        default:
+            return state;
+    }
 };
index fbb3d53..df2efbe 100644 (file)
@@ -26,48 +26,113 @@ import Protocols from './nicEditorComponents/Protocols.jsx';
 import NameAndPurpose from './nicEditorComponents/NameAndPurpose.jsx';
 
 class SoftwareProductComponentsNetworkEditorView extends React.Component {
+    render() {
+        let {
+            onCancel,
+            onValidateForm,
+            isReadOnlyMode,
+            isFormValid,
+            formReady,
+            data = {},
+            qgenericFieldInfo,
+            dataMap,
+            onDataChanged,
+            protocols,
+            onQDataChanged,
+            isManual,
+            genericFieldInfo
+        } = this.props;
+        let {
+            name,
+            description,
+            networkName,
+            networkType,
+            networkDescription
+        } = data;
+        let netWorkValues = [
+            {
+                enum: networkName,
+                title: networkName
+            }
+        ];
+        return (
+            <div>
+                {qgenericFieldInfo && (
+                    <Form
+                        ref={form => {
+                            this.form = form;
+                        }}
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        isValid={isFormValid}
+                        formReady={formReady}
+                        onValidateForm={() => onValidateForm()}
+                        className="vsp-components-network-editor">
+                        <div className="editor-data">
+                            <NameAndPurpose
+                                isManual={isManual}
+                                name={name}
+                                description={description}
+                                onDataChanged={onDataChanged}
+                                isReadOnlyMode={isReadOnlyMode}
+                                genericFieldInfo={genericFieldInfo}
+                            />
+                            <Protocols
+                                protocols={protocols}
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <IpConfig
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <Network
+                                networkDescription={networkDescription}
+                                onDataChanged={onDataChanged}
+                                networkValues={netWorkValues}
+                                isReadOnlyMode={isReadOnlyMode}
+                                networkType={networkType}
+                            />
+                            <Sizing
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <InFlowTraffic
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <OutFlowTraffic
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <FlowLength
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                            <Acceptable
+                                qgenericFieldInfo={qgenericFieldInfo}
+                                dataMap={dataMap}
+                                onQDataChanged={onQDataChanged}
+                            />
+                        </div>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       render() {
-               let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, qgenericFieldInfo,
-                       dataMap, onDataChanged, protocols, onQDataChanged, isManual, genericFieldInfo} = this.props;
-               let {name, description, networkName, networkType, networkDescription} = data;
-               let netWorkValues = [{
-                       enum: networkName,
-                       title: networkName
-               }];
-               return (
-                       <div>
-               {qgenericFieldInfo && <Form
-                       ref={(form) => { this.form = form; }}
-                       hasButtons={true}
-                       onSubmit={ () => this.submit() }
-                       onReset={ () => onCancel() }
-                       labledButtons={true}
-                       isReadOnlyMode={isReadOnlyMode}
-                       isValid={isFormValid}
-                       formReady={formReady}
-                       onValidateForm={() => onValidateForm() }
-                       className='vsp-components-network-editor'>
-                               <div className='editor-data'>
-                                       <NameAndPurpose isManual={isManual}  name={name} description={description} onDataChanged={onDataChanged} isReadOnlyMode={isReadOnlyMode} genericFieldInfo={genericFieldInfo} />
-                                       <Protocols protocols={protocols} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <IpConfig dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <Network networkDescription={networkDescription} onDataChanged={onDataChanged} networkValues={netWorkValues}  isReadOnlyMode={isReadOnlyMode} networkType={networkType}  />
-                                       <Sizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <InFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <OutFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <FlowLength qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                                       <Acceptable qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
-                               </div>
-                       </Form> }
-                       </div>
-               );
-       }
-
-       submit() {
-               let {data, qdata, onSubmit} = this.props;
-               onSubmit({data, qdata});
-       }
+    submit() {
+        let { data, qdata, onSubmit } = this.props;
+        onSubmit({ data, qdata });
+    }
 }
 
 export default SoftwareProductComponentsNetworkEditorView;
index 5cfc88b..a2e6514 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
+import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.NIC_LIST_UPDATE:
-                       return [...action.response];
-               case actionTypes.NIC_LIST_EDIT:
-                       const indexForEdit = state.findIndex(nic => nic.id === action.nic.id);
-                       return [...state.slice(0, indexForEdit), action.nic, ...state.slice(indexForEdit + 1)];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.NIC_LIST_UPDATE:
+            return [...action.response];
+        case actionTypes.NIC_LIST_EDIT:
+            const indexForEdit = state.findIndex(
+                nic => nic.id === action.nic.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.nic,
+                ...state.slice(indexForEdit + 1)
+            ];
+        default:
+            return state;
+    }
 };
index 1ffbc59..58c8161 100644 (file)
@@ -17,127 +17,223 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
-import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
-import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper as modalPagesMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js';
+import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper as modalPagesMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
+import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
 
 function baseUrl(softwareProductId, version, componentId) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`;
 }
 
-function createNIC({nic, vspId, componentId, version}) {
-       return RestAPIUtil.post(baseUrl(vspId, version, componentId), {
-               name: nic.name,
-               description: nic.description,
-               networkDescription: nic.networkDescription,
-               networkType: nic.networkType
-       });
+function createNIC({ nic, vspId, componentId, version }) {
+    return RestAPIUtil.post(baseUrl(vspId, version, componentId), {
+        name: nic.name,
+        description: nic.description,
+        networkDescription: nic.networkDescription,
+        networkType: nic.networkType
+    });
 }
 
-function fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`);
+function fetchNICQuestionnaire({
+    softwareProductId,
+    version,
+    componentId,
+    nicId
+}) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(
+            softwareProductId,
+            version,
+            componentId
+        )}/${nicId}/questionnaire`
+    );
 }
 
-function fetchNIC({softwareProductId, version, componentId, nicId}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`);
+function fetchNIC({ softwareProductId, version, componentId, nicId }) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version, componentId)}/${nicId}`
+    );
 }
 
-function fetchNICsList({softwareProductId, version, componentId}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
+function fetchNICsList({ softwareProductId, version, componentId }) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version, componentId)}`
+    );
 }
 
-function deleteNIC({softwareProductId, componentId, nicId, version}) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`);
+function deleteNIC({ softwareProductId, componentId, nicId, version }) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version, componentId)}/${nicId}`
+    );
 }
-function saveNIC({softwareProductId, version, componentId, nic: {id, name, description, networkId, networkType, networkDescription}}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{
-               name,
-               description,
-               networkId,
-               networkDescription,
-               networkType
-       });
+function saveNIC({
+    softwareProductId,
+    version,
+    componentId,
+    nic: { id, name, description, networkId, networkType, networkDescription }
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version, componentId)}/${id}`,
+        {
+            name,
+            description,
+            networkId,
+            networkDescription,
+            networkType
+        }
+    );
 }
 
-function saveNICQuestionnaire({softwareProductId, version, componentId, nicId, qdata}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`, qdata);
+function saveNICQuestionnaire({
+    softwareProductId,
+    version,
+    componentId,
+    nicId,
+    qdata
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(
+            softwareProductId,
+            version,
+            componentId
+        )}/${nicId}/questionnaire`,
+        qdata
+    );
 }
 
 const SoftwareProductComponentNetworkActionHelper = {
-
-       fetchNICsList(dispatch, {softwareProductId, version, componentId}) {
-               return fetchNICsList({softwareProductId, version, componentId}).then((response) => {
-                       dispatch({
-                               type: actionTypes.NIC_LIST_UPDATE,
-                               response: response.results
-                       });
-               });
-       },
-
-       openNICEditor(dispatch, {nic = {}, data = {}, softwareProductId, componentId, isReadOnlyMode, modalClassName, version}) {
-               dispatch({
-                       type: actionTypes.NICEditor.FILL_DATA,
-                       nic: {...data, id: nic.id}
-               });
-               dispatch({
-                       type: GlobalModalActions.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalClassName,
-                               modalComponentProps: {softwareProductId, componentId, isReadOnlyMode, version},
-                               modalComponentName: modalPagesMapper.NIC_EDITOR,
-                               title: i18n('Edit NIC')
-                       }
-               });
-       },
-
-       closeNICEditor(dispatch) {
-               dispatch({
-                       type: GlobalModalActions.GLOBAL_MODAL_CLOSE
-               });
-               dispatch({
-                       type: actionTypes.NICEditor.CLEAR_DATA
-               });
-       },
-
-       createNIC(dispatch, {nic, softwareProductId, componentId, version}){
-               return createNIC({nic, vspId: softwareProductId, componentId, version}).then(() => {
-                       return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
-               });
-       },
-       loadNICData({softwareProductId, version, componentId, nicId}) {
-               return fetchNIC({softwareProductId, version, componentId, nicId});
-       },
-
-       deleteNIC(dispatch, {softwareProductId, componentId, nicId, version}) {
-               return deleteNIC({softwareProductId, componentId, nicId, version}).then(() => {
-                       return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
-               });
-       },
-       loadNICQuestionnaire(dispatch, {softwareProductId, version, componentId, nicId}) {
-               return fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}).then((response) => {
-                       ValidationHelper.qDataLoaded(dispatch, {qName: NIC_QUESTIONNAIRE ,response: {
-                               qdata: response.data ? JSON.parse(response.data) : {},
-                               qschema: JSON.parse(response.schema)
-                       }});
-               });
-       },
-
-       saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}) {
-               SoftwareProductComponentNetworkActionHelper.closeNICEditor(dispatch);
-               return Promise.all([
-                       saveNICQuestionnaire({softwareProductId, version, componentId, nicId: data.id, qdata}),
-                       saveNIC({softwareProductId, version, componentId, nic: data}).then(() => {
-                               dispatch({
-                                       type: actionTypes.NIC_LIST_EDIT,
-                                       nic: data
-                               });
-                       })
-               ]);
-       }
+    fetchNICsList(dispatch, { softwareProductId, version, componentId }) {
+        return fetchNICsList({ softwareProductId, version, componentId }).then(
+            response => {
+                dispatch({
+                    type: actionTypes.NIC_LIST_UPDATE,
+                    response: response.results
+                });
+            }
+        );
+    },
+
+    openNICEditor(
+        dispatch,
+        {
+            nic = {},
+            data = {},
+            softwareProductId,
+            componentId,
+            isReadOnlyMode,
+            modalClassName,
+            version
+        }
+    ) {
+        dispatch({
+            type: actionTypes.NICEditor.FILL_DATA,
+            nic: { ...data, id: nic.id }
+        });
+        dispatch({
+            type: GlobalModalActions.GLOBAL_MODAL_SHOW,
+            data: {
+                modalClassName,
+                modalComponentProps: {
+                    softwareProductId,
+                    componentId,
+                    isReadOnlyMode,
+                    version
+                },
+                modalComponentName: modalPagesMapper.NIC_EDITOR,
+                title: i18n('Edit NIC')
+            }
+        });
+    },
+
+    closeNICEditor(dispatch) {
+        dispatch({
+            type: GlobalModalActions.GLOBAL_MODAL_CLOSE
+        });
+        dispatch({
+            type: actionTypes.NICEditor.CLEAR_DATA
+        });
+    },
+
+    createNIC(dispatch, { nic, softwareProductId, componentId, version }) {
+        return createNIC({
+            nic,
+            vspId: softwareProductId,
+            componentId,
+            version
+        }).then(() => {
+            return SoftwareProductComponentNetworkActionHelper.fetchNICsList(
+                dispatch,
+                { softwareProductId, componentId, version }
+            );
+        });
+    },
+    loadNICData({ softwareProductId, version, componentId, nicId }) {
+        return fetchNIC({ softwareProductId, version, componentId, nicId });
+    },
+
+    deleteNIC(dispatch, { softwareProductId, componentId, nicId, version }) {
+        return deleteNIC({
+            softwareProductId,
+            componentId,
+            nicId,
+            version
+        }).then(() => {
+            return SoftwareProductComponentNetworkActionHelper.fetchNICsList(
+                dispatch,
+                { softwareProductId, componentId, version }
+            );
+        });
+    },
+    loadNICQuestionnaire(
+        dispatch,
+        { softwareProductId, version, componentId, nicId }
+    ) {
+        return fetchNICQuestionnaire({
+            softwareProductId,
+            version,
+            componentId,
+            nicId
+        }).then(response => {
+            ValidationHelper.qDataLoaded(dispatch, {
+                qName: NIC_QUESTIONNAIRE,
+                response: {
+                    qdata: response.data ? JSON.parse(response.data) : {},
+                    qschema: JSON.parse(response.schema)
+                }
+            });
+        });
+    },
+
+    saveNICDataAndQuestionnaire(
+        dispatch,
+        { softwareProductId, version, componentId, data, qdata }
+    ) {
+        SoftwareProductComponentNetworkActionHelper.closeNICEditor(dispatch);
+        return Promise.all([
+            saveNICQuestionnaire({
+                softwareProductId,
+                version,
+                componentId,
+                nicId: data.id,
+                qdata
+            }),
+            saveNIC({
+                softwareProductId,
+                version,
+                componentId,
+                nic: data
+            }).then(() => {
+                dispatch({
+                    type: actionTypes.NIC_LIST_EDIT,
+                    nic: data
+                });
+            })
+        ]);
+    }
 };
 
 export default SoftwareProductComponentNetworkActionHelper;
index 8ef8fe8..4e361bb 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       NIC_LIST_EDIT: null,
-       NIC_LIST_UPDATE: null,
+    NIC_LIST_EDIT: null,
+    NIC_LIST_UPDATE: null,
 
-       NICEditor: {
-               FILL_DATA: null,
-               CLEAR_DATA: null,
-       },
-       NICCreation: {
-               OPEN: null,
-               CLEAR_DATA: null,
-               DATA_CHANGED: null
-       },
+    NICEditor: {
+        FILL_DATA: null,
+        CLEAR_DATA: null
+    },
+    NICCreation: {
+        OPEN: null,
+        CLEAR_DATA: null,
+        DATA_CHANGED: null
+    }
 });
 
 export const networkTypes = {
-       EXTERNAL: 'External',
-       INTERNAL: 'Internal'
+    EXTERNAL: 'External',
+    INTERNAL: 'Internal'
 };
 export const NIC_QUESTIONNAIRE = 'nic';
 export const NIC_CREATION_FORM_NAME = 'nicCreation';
index bb256d5..ac70852 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js';
 import SoftwareProductComponentsNetworkListView from './SoftwareProductComponentsNetworkListView.jsx';
 import SoftwareProductComponentsNetworkActionHelper from './SoftwareProductComponentsNetworkActionHelper.js';
-import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js';
 import NICCreationActionHelper from './NICCreation/NICCreationActionHelper.js';
-import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
+import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js';
 
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct = {},
+            isValidityData = true
+        },
+        softwareProductComponents
+    } = softwareProduct;
+    let {
+        network: { nicList = [] },
+        componentEditor: {
+            data: componentData,
+            qdata,
+            dataMap,
+            qgenericFieldInfo
+        }
+    } = softwareProductComponents;
+    let { version, onboardingMethod } = currentSoftwareProduct;
+    let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
 
-export const mapStateToProps = ({softwareProduct}) => {
-
-       let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
-       let {network: {nicList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
-       let {version, onboardingMethod} = currentSoftwareProduct;
-       let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
-
-       return {
-               version,
-               componentData,
-               qdata,
-               dataMap,
-               qgenericFieldInfo,
-               isValidityData,
-               nicList,
-               isManual
-       };
-
+    return {
+        version,
+        componentData,
+        qdata,
+        dataMap,
+        qgenericFieldInfo,
+        isValidityData,
+        nicList,
+        isManual
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
-       return {
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
-                       qName: COMPONENTS_QUESTIONNAIRE}),
-               onAddNic: () => NICCreationActionHelper.open(dispatch, {softwareProductId, componentId, modalClassName: 'network-nic-modal-create', version}),
-               onDeleteNic: (nic) => dispatch({
-                       type: GlobalModalActions.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{name}"?', {name: nic.name}),
-                               onConfirmed: () => SoftwareProductComponentsNetworkActionHelper.deleteNIC(dispatch, {softwareProductId,
-                                       componentId, nicId: nic.id, version})
-                       }
-               }),
-               onEditNicClick: (nic, isReadOnlyMode) => {
-                       Promise.all([
-                               SoftwareProductComponentsNetworkActionHelper.loadNICData({
-                                       softwareProductId,
-                                       version,
-                                       componentId,
-                                       nicId: nic.id
-                               }),
-                               SoftwareProductComponentsNetworkActionHelper.loadNICQuestionnaire(dispatch, {
-                                       softwareProductId,
-                                       version,
-                                       componentId,
-                                       nicId: nic.id
-                               })
-                       ]).then(
-                               ([{data}]) => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch, {nic, data,
-                                       isReadOnlyMode, softwareProductId, componentId, modalClassName: 'network-nic-modal-edit', version})
-                       );
-               },
-               onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
-                       {softwareProductId, version,
-                       vspComponentId: componentId,
-                       qdata});
-               }
-
-
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, componentId, version }
+) => {
+    return {
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onAddNic: () =>
+            NICCreationActionHelper.open(dispatch, {
+                softwareProductId,
+                componentId,
+                modalClassName: 'network-nic-modal-create',
+                version
+            }),
+        onDeleteNic: nic =>
+            dispatch({
+                type: GlobalModalActions.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{name}"?', {
+                        name: nic.name
+                    }),
+                    onConfirmed: () =>
+                        SoftwareProductComponentsNetworkActionHelper.deleteNIC(
+                            dispatch,
+                            {
+                                softwareProductId,
+                                componentId,
+                                nicId: nic.id,
+                                version
+                            }
+                        )
+                }
+            }),
+        onEditNicClick: (nic, isReadOnlyMode) => {
+            Promise.all([
+                SoftwareProductComponentsNetworkActionHelper.loadNICData({
+                    softwareProductId,
+                    version,
+                    componentId,
+                    nicId: nic.id
+                }),
+                SoftwareProductComponentsNetworkActionHelper.loadNICQuestionnaire(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        version,
+                        componentId,
+                        nicId: nic.id
+                    }
+                )
+            ]).then(([{ data }]) =>
+                SoftwareProductComponentsNetworkActionHelper.openNICEditor(
+                    dispatch,
+                    {
+                        nic,
+                        data,
+                        isReadOnlyMode,
+                        softwareProductId,
+                        componentId,
+                        modalClassName: 'network-nic-modal-edit',
+                        version
+                    }
+                )
+            );
+        },
+        onSubmit: ({ qdata }) => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    vspComponentId: componentId,
+                    qdata
+                }
+            );
+        }
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsNetworkListView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsNetworkListView);
index 4d460c7..c631fb2 100644 (file)
@@ -20,138 +20,203 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
-import Input from'nfvo-components/input/validation/Input.jsx';
-
+import Input from 'nfvo-components/input/validation/Input.jsx';
 
 class SoftwareProductComponentsNetworkView extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
-
-       render() {
-               let {dataMap, qgenericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props;
-
-               return(
-                       <div className='vsp-components-network'>
-                               <div className='network-data'>
-                                       <div>
-{ qgenericFieldInfo && <Form
-       formReady={null}
-       isValid={true}
-       onSubmit={() => this.save()}
-       isReadOnlyMode={isReadOnlyMode}
-       hasButtons={false}>
-                                                       <h3 className='section-title'>{i18n('Network Capacity')}</h3>
-                                                       <div className='rows-section'>
-                                                               <div className='row-flex-components'>
-                                                                       <div className='single-col'>
-                                                                               <Input
-                                                                                       data-test-id='protocolWithHighestTrafficProfileAcrossAllNICs'
-                                                                                       label={i18n('Protocol with Highest Traffic Profile across all NICs')}
-                                                                                       type='select'
-                                                                                       groupClassName='bootstrap-input-options'
-                                                                                       className='input-options-select'
-                                                                                       isValid={qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].isValid}
-                                                                                       errorText={qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].errorText}
-                                                                                       value={dataMap['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs']}
-                                                                                       onChange={(e) => {
-                                                                                               const selectedIndex = e.target.selectedIndex;
-                                                                                               const val = e.target.options[selectedIndex].value;
-                                                                                               onQDataChanged({'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' : val});}
-                                                                                       }>
-                                                                                       <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                                                                       { qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].enum.map(proto =>
-                                                                                               <option value={proto.enum} key={proto.enum}>{proto.title}</option>) }
-                                                                               </Input>
-                                                                       </div>
-                                                                       <div className='single-col add-line-break'>
-                                                                               <Input
-                                                                                       data-test-id='networkTransactionsPerSecond'
-                                                                                       label={i18n('Network Transactions per Second')}
-                                                                                       type='number'
-                                                                                       onChange={(ntps) => onQDataChanged({'network/networkCapacity/networkTransactionsPerSecond' : ntps})}
-                                                                                       isValid={qgenericFieldInfo['network/networkCapacity/networkTransactionsPerSecond'].isValid}
-                                                                                       errorText={qgenericFieldInfo['network/networkCapacity/networkTransactionsPerSecond'].errorText}
-                                                                                       value={dataMap['network/networkCapacity/networkTransactionsPerSecond']} />
-                                                                       </div>
-                                                                       <div className='empty-two-col' />
-                                                               </div>
-                                                       </div>
-
-                                               </Form> }
-                                       </div>
-                                       {this.renderNicList()}
-                               </div>
-
-                       </div>
-               );
-       }
-
-       renderNicList() {
-               const {localFilter} = this.state;
-               let {isReadOnlyMode, onAddNic, isManual} = this.props;
-               return (
-                       <ListEditorView
-                               title={i18n('Interfaces')}
-                               filterValue={localFilter}
-                               placeholder={i18n('Filter NICs by Name')}
-                               isReadOnlyMode={isReadOnlyMode}
-                               onFilter={value => this.setState({localFilter: value})}
-                               onAdd={isManual ? onAddNic : null}
-                               plusButtonTitle={i18n('Add NIC')}
-                               twoColumns>
-                               {this.filterList().map(nic => this.renderNicListItem(nic, isReadOnlyMode))}
-                       </ListEditorView>
-               );
-       }
+    render() {
+        let {
+            dataMap,
+            qgenericFieldInfo,
+            onQDataChanged,
+            isReadOnlyMode
+        } = this.props;
 
-       renderNicListItem(nic, isReadOnlyMode) {
-               let {id, name, description, networkName = ''} = nic;
-               let {onEditNicClick, version, isManual, onDeleteNic} =  this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               isReadOnlyMode={isReadOnlyMode}
-                               onSelect={() => onEditNicClick(nic, version, isReadOnlyMode)}
-                               onDelete={isManual ? () => onDeleteNic(nic, version) : null}>
+        return (
+            <div className="vsp-components-network">
+                <div className="network-data">
+                    <div>
+                        {qgenericFieldInfo && (
+                            <Form
+                                formReady={null}
+                                isValid={true}
+                                onSubmit={() => this.save()}
+                                isReadOnlyMode={isReadOnlyMode}
+                                hasButtons={false}>
+                                <h3 className="section-title">
+                                    {i18n('Network Capacity')}
+                                </h3>
+                                <div className="rows-section">
+                                    <div className="row-flex-components">
+                                        <div className="single-col">
+                                            <Input
+                                                data-test-id="protocolWithHighestTrafficProfileAcrossAllNICs"
+                                                label={i18n(
+                                                    'Protocol with Highest Traffic Profile across all NICs'
+                                                )}
+                                                type="select"
+                                                groupClassName="bootstrap-input-options"
+                                                className="input-options-select"
+                                                isValid={
+                                                    qgenericFieldInfo[
+                                                        'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'
+                                                    ].isValid
+                                                }
+                                                errorText={
+                                                    qgenericFieldInfo[
+                                                        'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'
+                                                    ].errorText
+                                                }
+                                                value={
+                                                    dataMap[
+                                                        'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'
+                                                    ]
+                                                }
+                                                onChange={e => {
+                                                    const selectedIndex =
+                                                        e.target.selectedIndex;
+                                                    const val =
+                                                        e.target.options[
+                                                            selectedIndex
+                                                        ].value;
+                                                    onQDataChanged({
+                                                        'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs': val
+                                                    });
+                                                }}>
+                                                <option
+                                                    key="placeholder"
+                                                    value="">
+                                                    {i18n('Select...')}
+                                                </option>
+                                                {qgenericFieldInfo[
+                                                    'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'
+                                                ].enum.map(proto => (
+                                                    <option
+                                                        value={proto.enum}
+                                                        key={proto.enum}>
+                                                        {proto.title}
+                                                    </option>
+                                                ))}
+                                            </Input>
+                                        </div>
+                                        <div className="single-col add-line-break">
+                                            <Input
+                                                data-test-id="networkTransactionsPerSecond"
+                                                label={i18n(
+                                                    'Network Transactions per Second'
+                                                )}
+                                                type="number"
+                                                onChange={ntps =>
+                                                    onQDataChanged({
+                                                        'network/networkCapacity/networkTransactionsPerSecond': ntps
+                                                    })
+                                                }
+                                                isValid={
+                                                    qgenericFieldInfo[
+                                                        'network/networkCapacity/networkTransactionsPerSecond'
+                                                    ].isValid
+                                                }
+                                                errorText={
+                                                    qgenericFieldInfo[
+                                                        'network/networkCapacity/networkTransactionsPerSecond'
+                                                    ].errorText
+                                                }
+                                                value={
+                                                    dataMap[
+                                                        'network/networkCapacity/networkTransactionsPerSecond'
+                                                    ]
+                                                }
+                                            />
+                                        </div>
+                                        <div className="empty-two-col" />
+                                    </div>
+                                </div>
+                            </Form>
+                        )}
+                    </div>
+                    {this.renderNicList()}
+                </div>
+            </div>
+        );
+    }
 
-                               <ListEditorItemViewField>
-                                       <div className='name'>{name}</div>
-                               </ListEditorItemViewField>
-                               <ListEditorItemViewField>
-                                       <div className={isManual ? 'details-col' : 'details'}>
-                                               <div className={isManual ? 'manual-title' : 'title'}>{i18n('Purpose of NIC')}</div>
-                                               {description && <div className={isManual ? 'description' : ''}>{description}</div>}
-                                       </div>
-                                       {!isManual && <div className='details'>
-                                               <div className='title'>{i18n('Network')}</div>
-                                               <div className='artifact-name'>{networkName}</div>
-                                       </div>}
-                               </ListEditorItemViewField>
+    renderNicList() {
+        const { localFilter } = this.state;
+        let { isReadOnlyMode, onAddNic, isManual } = this.props;
+        return (
+            <ListEditorView
+                title={i18n('Interfaces')}
+                filterValue={localFilter}
+                placeholder={i18n('Filter NICs by Name')}
+                isReadOnlyMode={isReadOnlyMode}
+                onFilter={value => this.setState({ localFilter: value })}
+                onAdd={isManual ? onAddNic : null}
+                plusButtonTitle={i18n('Add NIC')}
+                twoColumns>
+                {this.filterList().map(nic =>
+                    this.renderNicListItem(nic, isReadOnlyMode)
+                )}
+            </ListEditorView>
+        );
+    }
 
-                       </ListEditorItemView>
-               );
-       }
+    renderNicListItem(nic, isReadOnlyMode) {
+        let { id, name, description, networkName = '' } = nic;
+        let { onEditNicClick, version, isManual, onDeleteNic } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                isReadOnlyMode={isReadOnlyMode}
+                onSelect={() => onEditNicClick(nic, version, isReadOnlyMode)}
+                onDelete={isManual ? () => onDeleteNic(nic, version) : null}>
+                <ListEditorItemViewField>
+                    <div className="name">{name}</div>
+                </ListEditorItemViewField>
+                <ListEditorItemViewField>
+                    <div className={isManual ? 'details-col' : 'details'}>
+                        <div className={isManual ? 'manual-title' : 'title'}>
+                            {i18n('Purpose of NIC')}
+                        </div>
+                        {description && (
+                            <div className={isManual ? 'description' : ''}>
+                                {description}
+                            </div>
+                        )}
+                    </div>
+                    {!isManual && (
+                        <div className="details">
+                            <div className="title">{i18n('Network')}</div>
+                            <div className="artifact-name">{networkName}</div>
+                        </div>
+                    )}
+                </ListEditorItemViewField>
+            </ListEditorItemView>
+        );
+    }
 
-       filterList() {
-               let {nicList} = this.props;
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return nicList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return nicList;
-               }
-       }
+    filterList() {
+        let { nicList } = this.props;
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return nicList.filter(({ name = '', description = '' }) => {
+                return (
+                    escape(name).match(filter) ||
+                    escape(description).match(filter)
+                );
+            });
+        } else {
+            return nicList;
+        }
+    }
 
-       save() {
-               let {onSubmit, qdata, version} = this.props;
-               return onSubmit({qdata, version});
-       }
+    save() {
+        let { onSubmit, qdata, version } = this.props;
+        return onSubmit({ qdata, version });
+    }
 }
 
 export default SoftwareProductComponentsNetworkView;
index 0fc7404..0b2783e 100644 (file)
@@ -19,57 +19,97 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const Acceptable = ({qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return(
-               <GridSection hasLastColSet>
-                       <GridItem colSpan={3}>
-                               <div className='part-title-small packets'>{i18n('Acceptable Jitter')}</div>
-                       </GridItem>
-                       <GridItem lastColInRow>
-                               <div className='part-title-small bytes'>{i18n('Allow Packet Loss')}</div>
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       label={i18n('Mean')}
-                                       type='number'
-                                       data-test-id='acceptableJitter-mean'
-                                       isValid={qgenericFieldInfo['sizing/acceptableJitter/mean'].isValid}
-                                       errorText={qgenericFieldInfo['sizing/acceptableJitter/mean'].errorText}
-                                       value={dataMap['sizing/acceptableJitter/mean']}
-                                       onChange={val => onQDataChanged({'sizing/acceptableJitter/mean' : val})} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       label={i18n('Max')}
-                                       type='number'
-                                       data-test-id='acceptableJitter-max'
-                                       isValid={qgenericFieldInfo['sizing/acceptableJitter/max'].isValid}
-                                       errorText={qgenericFieldInfo['sizing/acceptableJitter/max'].errorText}
-                                       value={dataMap['sizing/acceptableJitter/max']}
-                                       onChange={val => onQDataChanged({'sizing/acceptableJitter/max' : val})} />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       label={i18n('Var')}
-                                       type='number'
-                                       data-test-id='acceptableJitter-variable'
-                                       isValid={qgenericFieldInfo['sizing/acceptableJitter/variable'].isValid}
-                                       errorText={qgenericFieldInfo['sizing/acceptableJitter/variable'].errorText}
-                                       value={dataMap['sizing/acceptableJitter/variable']}
-                                       onChange={val => onQDataChanged({'sizing/acceptableJitter/variable' : val})} />
-                       </GridItem>
-                       <GridItem lastColInRow>
-                               <Input
-                                       label={i18n('In Percent')}
-                                       type='number'
-                                       data-test-id='acceptableJitter-acceptablePacketLoss'
-                                       isValid={qgenericFieldInfo['sizing/acceptablePacketLoss'].isValid}
-                                       errorText={qgenericFieldInfo['sizing/acceptablePacketLoss'].errorText}
-                                       value={dataMap['sizing/acceptablePacketLoss']}
-                                       onChange={val => onQDataChanged({'sizing/acceptablePacketLoss' : val})} />
-                       </GridItem>
-               </GridSection>
-       );
+const Acceptable = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => {
+    return (
+        <GridSection hasLastColSet>
+            <GridItem colSpan={3}>
+                <div className="part-title-small packets">
+                    {i18n('Acceptable Jitter')}
+                </div>
+            </GridItem>
+            <GridItem lastColInRow>
+                <div className="part-title-small bytes">
+                    {i18n('Allow Packet Loss')}
+                </div>
+            </GridItem>
+            <GridItem>
+                <Input
+                    label={i18n('Mean')}
+                    type="number"
+                    data-test-id="acceptableJitter-mean"
+                    isValid={
+                        qgenericFieldInfo['sizing/acceptableJitter/mean']
+                            .isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['sizing/acceptableJitter/mean']
+                            .errorText
+                    }
+                    value={dataMap['sizing/acceptableJitter/mean']}
+                    onChange={val =>
+                        onQDataChanged({ 'sizing/acceptableJitter/mean': val })
+                    }
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    label={i18n('Max')}
+                    type="number"
+                    data-test-id="acceptableJitter-max"
+                    isValid={
+                        qgenericFieldInfo['sizing/acceptableJitter/max'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['sizing/acceptableJitter/max']
+                            .errorText
+                    }
+                    value={dataMap['sizing/acceptableJitter/max']}
+                    onChange={val =>
+                        onQDataChanged({ 'sizing/acceptableJitter/max': val })
+                    }
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    label={i18n('Var')}
+                    type="number"
+                    data-test-id="acceptableJitter-variable"
+                    isValid={
+                        qgenericFieldInfo['sizing/acceptableJitter/variable']
+                            .isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['sizing/acceptableJitter/variable']
+                            .errorText
+                    }
+                    value={dataMap['sizing/acceptableJitter/variable']}
+                    onChange={val =>
+                        onQDataChanged({
+                            'sizing/acceptableJitter/variable': val
+                        })
+                    }
+                />
+            </GridItem>
+            <GridItem lastColInRow>
+                <Input
+                    label={i18n('In Percent')}
+                    type="number"
+                    data-test-id="acceptableJitter-acceptablePacketLoss"
+                    isValid={
+                        qgenericFieldInfo['sizing/acceptablePacketLoss'].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['sizing/acceptablePacketLoss']
+                            .errorText
+                    }
+                    value={dataMap['sizing/acceptablePacketLoss']}
+                    onChange={val =>
+                        onQDataChanged({ 'sizing/acceptablePacketLoss': val })
+                    }
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 export default Acceptable;
index 3745fc7..32a5516 100644 (file)
@@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import PacketsBytes from './PacketsBytes.jsx';
 
 const pointers = [
-               {label: 'Peak', value: 'sizing/flowLength/packets/peak'},
-               {label: 'Avg', value: 'sizing/flowLength/packets/avg'},
-               {label: 'Peak', value: 'sizing/flowLength/bytes/peak'},
-               {label: 'Avg', value: 'sizing/flowLength/bytes/avg'},
+    { label: 'Peak', value: 'sizing/flowLength/packets/peak' },
+    { label: 'Avg', value: 'sizing/flowLength/packets/avg' },
+    { label: 'Peak', value: 'sizing/flowLength/bytes/peak' },
+    { label: 'Avg', value: 'sizing/flowLength/bytes/avg' }
 ];
 
-const  FlowLength = (props) => {
-       return(
-               <PacketsBytes {...props} title={i18n('Flow Length')} pointers={pointers}/>
-       );
+const FlowLength = props => {
+    return (
+        <PacketsBytes
+            {...props}
+            title={i18n('Flow Length')}
+            pointers={pointers}
+        />
+    );
 };
 
 export default FlowLength;
-
-
index 5476ed9..150e58a 100644 (file)
@@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import PacketsBytes from './PacketsBytes.jsx';
 
 const pointers = [
-               {label: 'Peak', value: 'sizing/inflowTrafficPerSecond/packets/peak'},
-               {label: 'Avg', value: 'sizing/inflowTrafficPerSecond/packets/avg'},
-               {label: 'Peak', value: 'sizing/inflowTrafficPerSecond/bytes/peak'},
-               {label: 'Avg', value: 'sizing/inflowTrafficPerSecond/bytes/avg'},
+    { label: 'Peak', value: 'sizing/inflowTrafficPerSecond/packets/peak' },
+    { label: 'Avg', value: 'sizing/inflowTrafficPerSecond/packets/avg' },
+    { label: 'Peak', value: 'sizing/inflowTrafficPerSecond/bytes/peak' },
+    { label: 'Avg', value: 'sizing/inflowTrafficPerSecond/bytes/avg' }
 ];
 
-const InFlowTraffic = (props) => {
-       return(
-               <PacketsBytes {...props} title={i18n('Inflow Traffic per second')} pointers={pointers}/>
-       );
+const InFlowTraffic = props => {
+    return (
+        <PacketsBytes
+            {...props}
+            title={i18n('Inflow Traffic per second')}
+            pointers={pointers}
+        />
+    );
 };
 
 export default InFlowTraffic;
-
-
index b3a5d21..6958356 100644 (file)
@@ -19,27 +19,37 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const IpConfig = ({dataMap, onQDataChanged}) => {
-       return (
-               <GridSection title={i18n('IP Configuration')}>
-                               <GridItem>
-                                       <Input
-                                               label={i18n('IPv4 Required')}
-                                               type='checkbox'
-                                               onChange={value => onQDataChanged({'ipConfiguration/ipv4Required' : value})}
-                                               data-test-id='ipConfiguration-ipv4Required'
-                                               value={dataMap['ipConfiguration/ipv4Required']} />
-                               </GridItem>
-                               <GridItem>
-                                       <Input
-                                               label={i18n('IPv6 Required')}
-                                               type='checkbox'
-                                               data-test-id='ipConfiguration-ipv6Required'
-                                               onChange={value => onQDataChanged({'ipConfiguration/ipv6Required' : value})}
-                                               value={dataMap['ipConfiguration/ipv6Required']} />
-                               </GridItem>
-               </GridSection>
-       );
+const IpConfig = ({ dataMap, onQDataChanged }) => {
+    return (
+        <GridSection title={i18n('IP Configuration')}>
+            <GridItem>
+                <Input
+                    label={i18n('IPv4 Required')}
+                    type="checkbox"
+                    onChange={value =>
+                        onQDataChanged({
+                            'ipConfiguration/ipv4Required': value
+                        })
+                    }
+                    data-test-id="ipConfiguration-ipv4Required"
+                    value={dataMap['ipConfiguration/ipv4Required']}
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    label={i18n('IPv6 Required')}
+                    type="checkbox"
+                    data-test-id="ipConfiguration-ipv6Required"
+                    onChange={value =>
+                        onQDataChanged({
+                            'ipConfiguration/ipv6Required': value
+                        })
+                    }
+                    value={dataMap['ipConfiguration/ipv6Required']}
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 export default IpConfig;
index 06a2bb4..5a89239 100644 (file)
@@ -20,40 +20,48 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const NameAndPurpose = ({onDataChanged, genericFieldInfo, isReadOnlyMode, name, description, isManual}) => {
-
-       return (
-               <GridSection hastLastColSet>
-                       <GridItem colSpan={2}>
-                               <Input
-                                       label={i18n('Name')}
-                                       value={name}
-                                       data-test-id='nic-name'
-                                       disabled={!isManual}
-                                       isRequired={true}
-                                       onChange={name => onDataChanged({name})}
-                                       isValid={genericFieldInfo['name'].isValid}
-                                       errorText={genericFieldInfo['name'].errorText}
-                                       type='text' />
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                               <Input
-                                       label={i18n('Purpose of NIC')}
-                                       value={description}
-                                       data-test-id='nic-description'
-                                       onChange={description => onDataChanged({description})}
-                                       disabled={isReadOnlyMode}
-                                       type='textarea' />
-                       </GridItem>
-               </GridSection>
-       );
+const NameAndPurpose = ({
+    onDataChanged,
+    genericFieldInfo,
+    isReadOnlyMode,
+    name,
+    description,
+    isManual
+}) => {
+    return (
+        <GridSection hastLastColSet>
+            <GridItem colSpan={2}>
+                <Input
+                    label={i18n('Name')}
+                    value={name}
+                    data-test-id="nic-name"
+                    disabled={!isManual}
+                    isRequired={true}
+                    onChange={name => onDataChanged({ name })}
+                    isValid={genericFieldInfo['name'].isValid}
+                    errorText={genericFieldInfo['name'].errorText}
+                    type="text"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <Input
+                    label={i18n('Purpose of NIC')}
+                    value={description}
+                    data-test-id="nic-description"
+                    onChange={description => onDataChanged({ description })}
+                    disabled={isReadOnlyMode}
+                    type="textarea"
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 NameAndPurpose.PropTypes = {
-       name: PropTypes.string,
-       description: PropTypes.array,
-       onDataChanged: PropTypes.func,
-       isReadOnlyMode: PropTypes.bool,
+    name: PropTypes.string,
+    description: PropTypes.array,
+    onDataChanged: PropTypes.func,
+    isReadOnlyMode: PropTypes.bool
 };
 
 export default NameAndPurpose;
index 7e6712c..c440d2f 100644 (file)
@@ -21,56 +21,70 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 import { networkTypes } from '../SoftwareProductComponentsNetworkConstants.js';
 
-const Network = ({networkValues, networkType, networkDescription, onDataChanged, isReadOnlyMode}) => {
-       const isExternal = networkType === networkTypes.EXTERNAL;
-       return (
-               <GridSection title={i18n('Network')} hasLastColSet>
-                       <GridItem>
-                               <Input
-                                       label={i18n('Internal')}
-                                       disabled
-                                       checked={!isExternal}
-                                       data-test-id='nic-internal'
-                                       className='network-radio disabled'
-                                       type='radio' />
-                       </GridItem>
-                       <GridItem>
-                               <Input
-                                       label={i18n('External')}
-                                       disabled
-                                       checked={isExternal}
-                                       data-test-id='nic-external'
-                                       className='network-radio disabled'
-                                       type='radio' />
-                       </GridItem>
-                       <GridItem colSpan={2} lastColInRow>
-                       {
-                               isExternal ?
-                                       <Input
-                                               label={i18n('Network Description')}
-                                               value={networkDescription}
-                                               data-test-id='nic-network-description'
-                                               onChange={networkDescription => onDataChanged({networkDescription})}
-                                               disabled={isReadOnlyMode}
-                                               type='text' />
-                               :
-                                       <Input
-                                               label={i18n('Network')}
-                                               data-test-id='nic-network'
-                                               type='select'
-                                               className='input-options-select'
-                                               groupClassName='bootstrap-input-options'
-                                               disabled={true}>
-                                               {networkValues.map(val => <option key={val.enum} value={val.enum}>{val.title}</option>)}
-                                       </Input>
-                       }
-                       </GridItem>
-               </GridSection>
-       );
+const Network = ({
+    networkValues,
+    networkType,
+    networkDescription,
+    onDataChanged,
+    isReadOnlyMode
+}) => {
+    const isExternal = networkType === networkTypes.EXTERNAL;
+    return (
+        <GridSection title={i18n('Network')} hasLastColSet>
+            <GridItem>
+                <Input
+                    label={i18n('Internal')}
+                    disabled
+                    checked={!isExternal}
+                    data-test-id="nic-internal"
+                    className="network-radio disabled"
+                    type="radio"
+                />
+            </GridItem>
+            <GridItem>
+                <Input
+                    label={i18n('External')}
+                    disabled
+                    checked={isExternal}
+                    data-test-id="nic-external"
+                    className="network-radio disabled"
+                    type="radio"
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                {isExternal ? (
+                    <Input
+                        label={i18n('Network Description')}
+                        value={networkDescription}
+                        data-test-id="nic-network-description"
+                        onChange={networkDescription =>
+                            onDataChanged({ networkDescription })
+                        }
+                        disabled={isReadOnlyMode}
+                        type="text"
+                    />
+                ) : (
+                    <Input
+                        label={i18n('Network')}
+                        data-test-id="nic-network"
+                        type="select"
+                        className="input-options-select"
+                        groupClassName="bootstrap-input-options"
+                        disabled={true}>
+                        {networkValues.map(val => (
+                            <option key={val.enum} value={val.enum}>
+                                {val.title}
+                            </option>
+                        ))}
+                    </Input>
+                )}
+            </GridItem>
+        </GridSection>
+    );
 };
 
 Network.PropTypes = {
-       networkValues: PropTypes.array
+    networkValues: PropTypes.array
 };
 
-export default  Network;
+export default Network;
index 80a3d15..7173294 100644 (file)
@@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import PacketsBytes from './PacketsBytes.jsx';
 
 const pointers = [
-               {label: 'Peak', value: 'sizing/outflowTrafficPerSecond/packets/peak'},
-               {label: 'Avg', value: 'sizing/outflowTrafficPerSecond/packets/avg'},
-               {label: 'Peak', value: 'sizing/outflowTrafficPerSecond/bytes/peak'},
-               {label: 'Avg', value: 'sizing/outflowTrafficPerSecond/bytes/avg'},
+    { label: 'Peak', value: 'sizing/outflowTrafficPerSecond/packets/peak' },
+    { label: 'Avg', value: 'sizing/outflowTrafficPerSecond/packets/avg' },
+    { label: 'Peak', value: 'sizing/outflowTrafficPerSecond/bytes/peak' },
+    { label: 'Avg', value: 'sizing/outflowTrafficPerSecond/bytes/avg' }
 ];
 
-const OutFlowTraffic = (props) => {
-       return(
-               <PacketsBytes {...props} title={i18n('Outflow Traffic per second')} pointers={pointers}/>
-       );
+const OutFlowTraffic = props => {
+    return (
+        <PacketsBytes
+            {...props}
+            title={i18n('Outflow Traffic per second')}
+            pointers={pointers}
+        />
+    );
 };
 
 export default OutFlowTraffic;
-
-
index f5f28ae..070ac81 100644 (file)
@@ -20,47 +20,74 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const PointerInput = ({label, value, onQDataChanged, qgenericFieldInfo, dataMap, lastColInRow}) => {
-       return (
-               <GridItem lastColInRow={lastColInRow}>
-                       <Input
-                               label={i18n(label)}
-                               type='number'
-                               data-test-id={`${value}`}
-                               isValid={qgenericFieldInfo[value].isValid}
-                               errorText={qgenericFieldInfo[value].errorText}
-                               value={dataMap[value]}
-                               onChange={val => onQDataChanged({[value]: val})} />
-               </GridItem>
-       );
+const PointerInput = ({
+    label,
+    value,
+    onQDataChanged,
+    qgenericFieldInfo,
+    dataMap,
+    lastColInRow
+}) => {
+    return (
+        <GridItem lastColInRow={lastColInRow}>
+            <Input
+                label={i18n(label)}
+                type="number"
+                data-test-id={`${value}`}
+                isValid={qgenericFieldInfo[value].isValid}
+                errorText={qgenericFieldInfo[value].errorText}
+                value={dataMap[value]}
+                onChange={val => onQDataChanged({ [value]: val })}
+            />
+        </GridItem>
+    );
 };
 
 PointerInput.PropTypes = {
-       label: PropTypes.string,
-       value: PropTypes.string
+    label: PropTypes.string,
+    value: PropTypes.string
 };
 
-const PacketsBytes = ({title, pointers = [], qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return(
-               <GridSection title={title} hasLastColSet>
-                               <GridItem colSpan={2}>
-                                       <div className='part-title-small packets'>{i18n('Packets')}</div>
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow>
-                                       <div className='part-title-small bytes'>{i18n('Bytes')}</div>
-                               </GridItem>
-                               {pointers.map((pointer, i) => {return (<PointerInput key={i} label={pointer.label} value={pointer.value}
-                                       qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged} dataMap={dataMap} lastColInRow={i === 3} />);})}
-               </GridSection>
-       );
+const PacketsBytes = ({
+    title,
+    pointers = [],
+    qgenericFieldInfo,
+    dataMap,
+    onQDataChanged
+}) => {
+    return (
+        <GridSection title={title} hasLastColSet>
+            <GridItem colSpan={2}>
+                <div className="part-title-small packets">
+                    {i18n('Packets')}
+                </div>
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <div className="part-title-small bytes">{i18n('Bytes')}</div>
+            </GridItem>
+            {pointers.map((pointer, i) => {
+                return (
+                    <PointerInput
+                        key={i}
+                        label={pointer.label}
+                        value={pointer.value}
+                        qgenericFieldInfo={qgenericFieldInfo}
+                        onQDataChanged={onQDataChanged}
+                        dataMap={dataMap}
+                        lastColInRow={i === 3}
+                    />
+                );
+            })}
+        </GridSection>
+    );
 };
 
 PacketsBytes.PropTypes = {
-       title: PropTypes.string,
-       pointers: PropTypes.array,
-       onQDataChanged:  PropTypes.function,
-       dataMap: PropTypes.object,
-       qgenericFieldInfo: PropTypes.object
+    title: PropTypes.string,
+    pointers: PropTypes.array,
+    onQDataChanged: PropTypes.function,
+    dataMap: PropTypes.object,
+    qgenericFieldInfo: PropTypes.object
 };
 
 export default PacketsBytes;
index be4093d..eb762b1 100644 (file)
@@ -21,55 +21,83 @@ import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const Protocols = ({protocols, qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return (
-               <GridSection title={i18n('Protocols')} hasLastColSet>
-                               <GridItem colSpan={2}>
-                                       <InputOptions
-                                               data-test-id='nic-protocols'
-                                               label={i18n('Protocols')}
-                                               type='select'
-                                               isMultiSelect={true}
-                                               isValid={qgenericFieldInfo['protocols/protocols'].isValid}
-                                               errorText={qgenericFieldInfo['protocols/protocols'].errorText}
-                                               onInputChange={()=>{}}
-                                               onEnumChange={protocols => {
-                                                       onQDataChanged({'protocols/protocols' : protocols});}
-                                               }
-                                               multiSelectedEnum={dataMap['protocols/protocols']}
-                                               clearable={false}
-                                               values={qgenericFieldInfo['protocols/protocols'].enum}/>
-                               </GridItem>
-                               <GridItem colSpan={2} lastColInRow>
-                                       <Input
-                                               data-test-id='nic-protocolWithHighestTrafficProfile'
-                                               label={i18n('Protocol with Highest Traffic Profile')}
-                                               type='select'
-                                               groupClassName='bootstrap-input-options'
-                                               className='input-options-select'
-                                               isValid={qgenericFieldInfo['protocols/protocolWithHighestTrafficProfile'].isValid}
-                                               errorText={qgenericFieldInfo['protocols/protocolWithHighestTrafficProfile'].errorText}
-                                               value={dataMap['protocols/protocolWithHighestTrafficProfile']}
-                                               onChange={(e) => {
-                                                       const selectedIndex = e.target.selectedIndex;
-                                                       const val = e.target.options[selectedIndex].value;
-                                                       onQDataChanged({'protocols/protocolWithHighestTrafficProfile' : val});}
-                                               }>
-                                               {(protocols.length === 0) &&
-                                                       <option key={'You must select protocols first...'} value=''>{i18n('You must select protocols first...')}</option>
-                                               }
-                                               {protocols.map(protocol => <option key={protocol} value={protocol}>{protocol}</option>)}
-                                       </Input>
-                               </GridItem>
-               </GridSection>
-       );
+const Protocols = ({
+    protocols,
+    qgenericFieldInfo,
+    dataMap,
+    onQDataChanged
+}) => {
+    return (
+        <GridSection title={i18n('Protocols')} hasLastColSet>
+            <GridItem colSpan={2}>
+                <InputOptions
+                    data-test-id="nic-protocols"
+                    label={i18n('Protocols')}
+                    type="select"
+                    isMultiSelect={true}
+                    isValid={qgenericFieldInfo['protocols/protocols'].isValid}
+                    errorText={
+                        qgenericFieldInfo['protocols/protocols'].errorText
+                    }
+                    onInputChange={() => {}}
+                    onEnumChange={protocols => {
+                        onQDataChanged({ 'protocols/protocols': protocols });
+                    }}
+                    multiSelectedEnum={dataMap['protocols/protocols']}
+                    clearable={false}
+                    values={qgenericFieldInfo['protocols/protocols'].enum}
+                />
+            </GridItem>
+            <GridItem colSpan={2} lastColInRow>
+                <Input
+                    data-test-id="nic-protocolWithHighestTrafficProfile"
+                    label={i18n('Protocol with Highest Traffic Profile')}
+                    type="select"
+                    groupClassName="bootstrap-input-options"
+                    className="input-options-select"
+                    isValid={
+                        qgenericFieldInfo[
+                            'protocols/protocolWithHighestTrafficProfile'
+                        ].isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo[
+                            'protocols/protocolWithHighestTrafficProfile'
+                        ].errorText
+                    }
+                    value={
+                        dataMap['protocols/protocolWithHighestTrafficProfile']
+                    }
+                    onChange={e => {
+                        const selectedIndex = e.target.selectedIndex;
+                        const val = e.target.options[selectedIndex].value;
+                        onQDataChanged({
+                            'protocols/protocolWithHighestTrafficProfile': val
+                        });
+                    }}>
+                    {protocols.length === 0 && (
+                        <option
+                            key={'You must select protocols first...'}
+                            value="">
+                            {i18n('You must select protocols first...')}
+                        </option>
+                    )}
+                    {protocols.map(protocol => (
+                        <option key={protocol} value={protocol}>
+                            {protocol}
+                        </option>
+                    ))}
+                </Input>
+            </GridItem>
+        </GridSection>
+    );
 };
 
 Protocols.PropTypes = {
-       protocols: PropTypes.array,
-       onQDataChanged:  PropTypes.function,
-       dataMap: PropTypes.object,
-       qgenericFieldInfo: PropTypes.object
+    protocols: PropTypes.array,
+    onQDataChanged: PropTypes.function,
+    dataMap: PropTypes.object,
+    qgenericFieldInfo: PropTypes.object
 };
 
 export default Protocols;
index 202d458..f9ec726 100644 (file)
@@ -19,21 +19,32 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-const Sizing = ({qgenericFieldInfo, dataMap, onQDataChanged}) => {
-       return(
-               <GridSection title={i18n('Sizing')} hasLastColSet>
-                       <GridItem colSpan={4} lastColInRow>
-                               <Input
-                                       label={i18n('Describe Quality of Service')}
-                                       type='textarea'
-                                       data-test-id='sizing-describeQualityOfService'
-                                       isValid={qgenericFieldInfo['sizing/describeQualityOfService'].isValid}
-                                       errorText={qgenericFieldInfo['sizing/describeQualityOfService'].errorText}
-                                       value={dataMap['sizing/describeQualityOfService']}
-                                       onChange={val => onQDataChanged({'sizing/describeQualityOfService' : val}) }/>
-                       </GridItem>
-               </GridSection>
-       );
+const Sizing = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => {
+    return (
+        <GridSection title={i18n('Sizing')} hasLastColSet>
+            <GridItem colSpan={4} lastColInRow>
+                <Input
+                    label={i18n('Describe Quality of Service')}
+                    type="textarea"
+                    data-test-id="sizing-describeQualityOfService"
+                    isValid={
+                        qgenericFieldInfo['sizing/describeQualityOfService']
+                            .isValid
+                    }
+                    errorText={
+                        qgenericFieldInfo['sizing/describeQualityOfService']
+                            .errorText
+                    }
+                    value={dataMap['sizing/describeQualityOfService']}
+                    onChange={val =>
+                        onQDataChanged({
+                            'sizing/describeQualityOfService': val
+                        })
+                    }
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 export default Sizing;
index b2133ad..52c5cdd 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './SoftwareProductComponentProcessesConstants.js';
+import { actionTypes } from './SoftwareProductComponentProcessesConstants.js';
 
 function baseUrl(softwareProductId, version, componentId) {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${version.id}/components/${componentId}/processes`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${
+        version.id
+    }/components/${componentId}/processes`;
 }
 
-function fetchProcessesList({softwareProductId, version, componentId}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
+function fetchProcessesList({ softwareProductId, version, componentId }) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version, componentId)}`
+    );
 }
 
-function deleteProcess({softwareProductId, version, componentId, processId}) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${processId}`);
+function deleteProcess({ softwareProductId, version, componentId, processId }) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version, componentId)}/${processId}`
+    );
 }
 
-function putProcess({softwareProductId, version, componentId, process}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${process.id}`, {
-               name: process.name,
-               description: process.description,
-               type: process.type === '' ? null : process.type
-       });
+function putProcess({ softwareProductId, version, componentId, process }) {
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version, componentId)}/${process.id}`,
+        {
+            name: process.name,
+            description: process.description,
+            type: process.type === '' ? null : process.type
+        }
+    );
 }
 
-function postProcess({softwareProductId, version, componentId, process}) {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}`, {
-               name: process.name,
-               description: process.description,
-               type: process.type === '' ? null : process.type
-       });
+function postProcess({ softwareProductId, version, componentId, process }) {
+    return RestAPIUtil.post(
+        `${baseUrl(softwareProductId, version, componentId)}`,
+        {
+            name: process.name,
+            description: process.description,
+            type: process.type === '' ? null : process.type
+        }
+    );
 }
 
-function uploadFileToProcess({softwareProductId, version, processId, componentId, formData}) {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}/${processId}/upload`, formData);
+function uploadFileToProcess({
+    softwareProductId,
+    version,
+    processId,
+    componentId,
+    formData
+}) {
+    return RestAPIUtil.post(
+        `${baseUrl(
+            softwareProductId,
+            version,
+            componentId
+        )}/${processId}/upload`,
+        formData
+    );
 }
 
-
-
 const SoftwareProductComponentProcessesActionHelper = {
-       fetchProcessesList(dispatch, {softwareProductId, version, componentId}) {
-               dispatch({
-                       type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
-                       processesList: []
-               });
-
-               return fetchProcessesList({softwareProductId, version, componentId}).then(response => {
-                       dispatch({
-                               type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
-                               processesList: response.results
-                       });
-               });
-       },
-
-       deleteProcess(dispatch, {process, softwareProductId, version, componentId}) {
-               return deleteProcess({softwareProductId, version, processId:process.id, componentId}).then(() => {
-                       dispatch({
-                               type: actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
-                               processId: process.id
-                       });
-               });
-
-       },
-
-       saveProcess(dispatch, {softwareProductId, version, componentId, previousProcess, process}) {
-               if (previousProcess) {
-                       return putProcess({softwareProductId, version, componentId,  process}).then(() => {
-                               if (process.formData && process.formData.name !== previousProcess.artifactName){
-                                       uploadFileToProcess({softwareProductId, version, processId: process.id, formData: process.formData, componentId});
-                               }
-                               dispatch({
-                                       type: actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
-                                       process
-                               });
-                       });
-               }
-               else {
-                       return postProcess({softwareProductId, version, componentId, process}).then(response => {
-                               if (process.formData) {
-                                       uploadFileToProcess({softwareProductId, version, processId: response.value, formData: process.formData, componentId});
-                               }
-                               dispatch({
-                                       type: actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
-                                       process: {
-                                               ...process,
-                                               id: response.value
-                                       }
-                               });
-                       });
-               }
-       },
-
-       hideDeleteConfirm(dispatch) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM,
-                       processToDelete: false
-               });
-       },
-
-       openDeleteProcessesConfirm(dispatch, {process} ) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM,
-                       processToDelete: process
-               });
-       },
-
-       openEditor(dispatch, process = {}) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN,
-                       process
-               });
-       },
-       closeEditor(dispatch) {
-               dispatch({
-                       type:actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE
-               });
-       }
+    fetchProcessesList(dispatch, { softwareProductId, version, componentId }) {
+        dispatch({
+            type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
+            processesList: []
+        });
+
+        return fetchProcessesList({
+            softwareProductId,
+            version,
+            componentId
+        }).then(response => {
+            dispatch({
+                type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
+                processesList: response.results
+            });
+        });
+    },
+
+    deleteProcess(
+        dispatch,
+        { process, softwareProductId, version, componentId }
+    ) {
+        return deleteProcess({
+            softwareProductId,
+            version,
+            processId: process.id,
+            componentId
+        }).then(() => {
+            dispatch({
+                type: actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
+                processId: process.id
+            });
+        });
+    },
+
+    saveProcess(
+        dispatch,
+        { softwareProductId, version, componentId, previousProcess, process }
+    ) {
+        if (previousProcess) {
+            return putProcess({
+                softwareProductId,
+                version,
+                componentId,
+                process
+            }).then(() => {
+                if (
+                    process.formData &&
+                    process.formData.name !== previousProcess.artifactName
+                ) {
+                    uploadFileToProcess({
+                        softwareProductId,
+                        version,
+                        processId: process.id,
+                        formData: process.formData,
+                        componentId
+                    });
+                }
+                dispatch({
+                    type: actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
+                    process
+                });
+            });
+        } else {
+            return postProcess({
+                softwareProductId,
+                version,
+                componentId,
+                process
+            }).then(response => {
+                if (process.formData) {
+                    uploadFileToProcess({
+                        softwareProductId,
+                        version,
+                        processId: response.value,
+                        formData: process.formData,
+                        componentId
+                    });
+                }
+                dispatch({
+                    type: actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
+                    process: {
+                        ...process,
+                        id: response.value
+                    }
+                });
+            });
+        }
+    },
+
+    hideDeleteConfirm(dispatch) {
+        dispatch({
+            type:
+                actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM,
+            processToDelete: false
+        });
+    },
+
+    openDeleteProcessesConfirm(dispatch, { process }) {
+        dispatch({
+            type:
+                actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM,
+            processToDelete: process
+        });
+    },
+
+    openEditor(dispatch, process = {}) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN,
+            process
+        });
+    },
+    closeEditor(dispatch) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE
+        });
+    }
 };
 
 export default SoftwareProductComponentProcessesActionHelper;
index d15432b..e3ce4f8 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
-       EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
-       DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
-       SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: null,
-       SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: null,
-       FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: null,
-       SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM: null
+    ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
+    EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
+    DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null,
+    SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: null,
+    SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: null,
+    FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: null,
+    SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM: null
 });
 
 export const optionsInputValues = {
-       PROCESS_TYPE: [
-               {title: 'Select...', enum: ''},
-               {title: 'Lifecycle Operations', enum: 'Lifecycle_Operations'},
-               {title: 'Other', enum: 'Other'}
-       ]
+    PROCESS_TYPE: [
+        { title: 'Select...', enum: '' },
+        { title: 'Lifecycle Operations', enum: 'Lifecycle_Operations' },
+        { title: 'Other', enum: 'Other' }
+    ]
 };
 
-export const SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM = 'SOFTWAREPRODUCTPROCESSCOMPONENTSEDITORFORM';
+export const SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM =
+    'SOFTWAREPRODUCTPROCESSCOMPONENTSEDITORFORM';
index 9502e24..9d2bf34 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper';
 import SoftwareProductComponentProcessesEditorView from './SoftwareProductComponentProcessesEditorView.jsx';
-import {SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM} from './SoftwareProductComponentProcessesConstants.js';
+import { SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM } from './SoftwareProductComponentProcessesConstants.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductComponents: {componentProcesses = {}}} = softwareProduct;
-       let {processesList = [], processesEditor = {}} = componentProcesses;
-       let {data, genericFieldInfo, formReady} = processesEditor;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductComponents: { componentProcesses = {} }
+    } = softwareProduct;
+    let { processesList = [], processesEditor = {} } = componentProcesses;
+    let { data, genericFieldInfo, formReady } = processesEditor;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let previousData;
-       const processId = data ? data.id : null;
-       if(processId) {
-               previousData = processesList.find(process => process.id === processId);
-       }
+    let previousData;
+    const processId = data ? data.id : null;
+    if (processId) {
+        previousData = processesList.find(process => process.id === processId);
+    }
 
-       return {
-               data,
-               genericFieldInfo,
-               previousData,
-               isFormValid,
-               formReady
-       };
+    return {
+        data,
+        genericFieldInfo,
+        previousData,
+        isFormValid,
+        formReady
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
-
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM}),
-               onCancel: () => SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch),
-               onSubmit: ({previousProcess, process}) => {
-                       SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch);
-                       SoftwareProductComponentProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, componentId, process});
-               },
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM)
-       };
+const mapActionsToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM
+            }),
+        onCancel: () =>
+            SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch),
+        onSubmit: ({ previousProcess, process }) => {
+            SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch);
+            SoftwareProductComponentProcessesActionHelper.saveProcess(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    previousProcess,
+                    componentId,
+                    process
+                }
+            );
+        },
+        onValidateForm: () =>
+            ValidationHelper.validateForm(
+                dispatch,
+                SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM
+            )
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentProcessesEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductComponentProcessesEditorView
+);
index 9afaa6d..fd21173 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM} from './SoftwareProductComponentProcessesConstants.js';
+import {
+    actionTypes,
+    SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM
+} from './SoftwareProductComponentProcessesConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN:
-                       return {
-                               ...state,
-                               formReady: null,
-                               formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM,
-                               genericFieldInfo: {
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'artifactName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'type' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               },
-                               data: action.process
-                       };
-               case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN:
+            return {
+                ...state,
+                formReady: null,
+                formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM,
+                genericFieldInfo: {
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    artifactName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    type: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                },
+                data: action.process
+            };
+        case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE:
+            return {};
+        default:
+            return state;
+    }
 };
index 9841ecb..132ebe8 100644 (file)
  * permissions and limitations under the License.
  */
 import React from 'react';
-import  {optionsInputValues as ComponentProcessesOptionsInputValues} from './SoftwareProductComponentProcessesConstants.js';
+import { optionsInputValues as ComponentProcessesOptionsInputValues } from './SoftwareProductComponentProcessesConstants.js';
 import SoftwareProductProcessesEditorForm from 'sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx';
 
-
 class SoftwareProductProcessesEditorView extends React.Component {
-
-       render() {
-               return (
-                       <SoftwareProductProcessesEditorForm optionsInputValues={ComponentProcessesOptionsInputValues} {...this.props}/>
-               );
-       }
+    render() {
+        return (
+            <SoftwareProductProcessesEditorForm
+                optionsInputValues={ComponentProcessesOptionsInputValues}
+                {...this.props}
+            />
+        );
+    }
 }
 
 export default SoftwareProductProcessesEditorView;
index 2a7152e..cb6d25a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper.js';
 
 import SoftwareProductComponentsProcessesListView from './SoftwareProductComponentsProcessesListView.jsx';
 
-export const mapStateToProps = ({softwareProduct}) => {
-
-       let {softwareProductEditor: {data:currentSoftwareProduct = {},  isValidityData = true}, softwareProductComponents: {componentProcesses = {}}} = softwareProduct;
-       let{processesList = [], processesEditor = {}} = componentProcesses;
-       let {data} = processesEditor;
-
-       return {
-               currentSoftwareProduct,
-               isValidityData,
-               processesList,
-               isDisplayModal: Boolean(data),
-               isModalInEditMode: Boolean(data && data.id)
-       };
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct = {},
+            isValidityData = true
+        },
+        softwareProductComponents: { componentProcesses = {} }
+    } = softwareProduct;
+    let { processesList = [], processesEditor = {} } = componentProcesses;
+    let { data } = processesEditor;
 
+    return {
+        currentSoftwareProduct,
+        isValidityData,
+        processesList,
+        isDisplayModal: Boolean(data),
+        isModalInEditMode: Boolean(data && data.id)
+    };
 };
 
-const mapActionsToProps = (dispatch, {componentId, softwareProductId, version}) => {
-
-       return {
-               onAddProcess: () => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch),
-               onEditProcess: (process) => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch, process),
-               onDeleteProcess: (process) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=> SoftwareProductComponentProcessesActionHelper.deleteProcess(dispatch,
-                                       {process, softwareProductId, version, componentId})
-                       }
-               })
-       };
+const mapActionsToProps = (
+    dispatch,
+    { componentId, softwareProductId, version }
+) => {
+    return {
+        onAddProcess: () =>
+            SoftwareProductComponentProcessesActionHelper.openEditor(dispatch),
+        onEditProcess: process =>
+            SoftwareProductComponentProcessesActionHelper.openEditor(
+                dispatch,
+                process
+            ),
+        onDeleteProcess: process =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{name}"?', {
+                        name: process.name
+                    }),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        SoftwareProductComponentProcessesActionHelper.deleteProcess(
+                            dispatch,
+                            { process, softwareProductId, version, componentId }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsProcessesListView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductComponentsProcessesListView);
index 98e24a9..d406f02 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductComponentProcessesConstants.js';
+import { actionTypes } from './SoftwareProductComponentProcessesConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES:
-                       return [...action.processesList];
-               case actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
-                       const indexForEdit = state.findIndex(process => process.id === action.process.id);
-                       return [...state.slice(0, indexForEdit), action.process, ...state.slice(indexForEdit + 1)];
-               case actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
-                       return [...state, action.process];
-               case actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
-                       return state.filter(process => process.id !== action.processId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES:
+            return [...action.processesList];
+        case actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
+            const indexForEdit = state.findIndex(
+                process => process.id === action.process.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.process,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
+            return [...state, action.process];
+        case actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS:
+            return state.filter(process => process.id !== action.processId);
+        default:
+            return state;
+    }
 };
index 27c4b9f..8fa2bff 100644 (file)
@@ -21,55 +21,73 @@ import SoftwareProductProcessesEditor from './SoftwareProductComponentProcessesE
 import SoftwareProductProcessListView from 'sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx';
 
 class SoftwareProductProcessesView extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
+    static propTypes = {
+        onAddProcess: PropTypes.func,
+        onEditProcess: PropTypes.func,
+        onDeleteProcess: PropTypes.func,
+        isDisplayModal: PropTypes.bool,
+        isModalInEditMode: PropTypes.bool,
+        onStorageSelect: PropTypes.func,
+        componentId: PropTypes.string,
+        softwareProductId: PropTypes.string,
+        currentSoftwareProduct: PropTypes.object
+    };
 
-       static propTypes = {
-               onAddProcess: PropTypes.func,
-               onEditProcess: PropTypes.func,
-               onDeleteProcess: PropTypes.func,
-               isDisplayModal: PropTypes.bool,
-               isModalInEditMode: PropTypes.bool,
-               onStorageSelect: PropTypes.func,
-               componentId: PropTypes.string,
-               softwareProductId: PropTypes.string,
-               currentSoftwareProduct: PropTypes.object
-       };
-
-       render() {
-               return (
-                       <div className='vsp-processes-page'>
-                               <div className='software-product-view'>
-                                       <div className='software-product-landing-view-right-side vsp-components-processes-page flex-column'>
-                                               {this.renderEditor()}
-                                               <SoftwareProductProcessListView addButtonTitle={i18n('Add Component Process Details')} {...this.props}/>
-                                       </div>
-                               </div>
-                       </div>
-               );
-       }
-
-       renderEditor() {
-               let {softwareProductId, version, componentId, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
-               return (
-                       <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal'>
-                               <Modal.Header>
-                                       <Modal.Title>{isModalInEditMode ? i18n('Edit Process Details') : i18n('Create New Process Details')}</Modal.Title>
-                               </Modal.Header>
-                               <Modal.Body className='edit-process-modal'>
-                                       <SoftwareProductProcessesEditor
-                                               componentId={componentId}
-                                               softwareProductId={softwareProductId}
-                                               version={version}
-                                               isReadOnlyMode={isReadOnlyMode}/>
-                               </Modal.Body>
-                       </Modal>
-
-               );
-       }
+    render() {
+        return (
+            <div className="vsp-processes-page">
+                <div className="software-product-view">
+                    <div className="software-product-landing-view-right-side vsp-components-processes-page flex-column">
+                        {this.renderEditor()}
+                        <SoftwareProductProcessListView
+                            addButtonTitle={i18n(
+                                'Add Component Process Details'
+                            )}
+                            {...this.props}
+                        />
+                    </div>
+                </div>
+            </div>
+        );
+    }
 
+    renderEditor() {
+        let {
+            softwareProductId,
+            version,
+            componentId,
+            isReadOnlyMode,
+            isDisplayModal,
+            isModalInEditMode
+        } = this.props;
+        return (
+            <Modal
+                show={isDisplayModal}
+                bsSize="large"
+                animation={true}
+                className="onborading-modal">
+                <Modal.Header>
+                    <Modal.Title>
+                        {isModalInEditMode
+                            ? i18n('Edit Process Details')
+                            : i18n('Create New Process Details')}
+                    </Modal.Title>
+                </Modal.Header>
+                <Modal.Body className="edit-process-modal">
+                    <SoftwareProductProcessesEditor
+                        componentId={componentId}
+                        softwareProductId={softwareProductId}
+                        version={version}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                </Modal.Body>
+            </Modal>
+        );
+    }
 }
 
 export default SoftwareProductProcessesView;
index ca27a76..8da9b99 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 
 import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js';
 import SoftwareProductComponentStorageView from './SoftwareProductComponentStorageView.jsx';
 
-import {COMPONENTS_QUESTIONNAIRE} from '../SoftwareProductComponentsConstants.js';
+import { COMPONENTS_QUESTIONNAIRE } from '../SoftwareProductComponentsConstants.js';
 
-const mapStateToProps = ({softwareProduct: {softwareProductComponents}}) => {
-       let {componentEditor: {qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap}} = softwareProductComponents;
+const mapStateToProps = ({
+    softwareProduct: { softwareProductComponents }
+}) => {
+    let {
+        componentEditor: {
+            qdata,
+            qgenericFieldInfo: qGenericFieldInfo,
+            dataMap
+        }
+    } = softwareProductComponents;
 
-       return {
-               qdata,
-               qGenericFieldInfo,
-               dataMap
-       };
+    return {
+        qdata,
+        qGenericFieldInfo,
+        dataMap
+    };
 };
 
-const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => {
-       return {
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
-               onSubmit: ({qdata}) => {
-                       return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});
-               }
-       };
+const mapActionToProps = (
+    dispatch,
+    { softwareProductId, version, componentId }
+) => {
+    return {
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: COMPONENTS_QUESTIONNAIRE
+            }),
+        onSubmit: ({ qdata }) => {
+            return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
+                dispatch,
+                {
+                    softwareProductId,
+                    version,
+                    vspComponentId: componentId,
+                    qdata
+                }
+            );
+        }
+    };
 };
 
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true}) (SoftwareProductComponentStorageView);
+export default connect(mapStateToProps, mapActionToProps, null, {
+    withRef: true
+})(SoftwareProductComponentStorageView);
index 8538dab..ac7e4a8 100644 (file)
@@ -22,171 +22,311 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 import classnames from 'classnames';
 
-const BackupSection = ({isReadOnlyMode,dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Backup')}>
-               <GridItem>
-                       <div className='vertical-flex'>
-                               <label key='label' className={classnames('control-label',{'disabled': isReadOnlyMode})}>{i18n('Backup Type')}</label>
-                               <div className='radio-options-content-row'>
-                                       {qgenericFieldInfo['storage/backup/backupType'].enum.map(onSite => (
-                                               <Input
-                                                       data-test-id='backupType'
-                                                       type='radio'
-                                                       key={onSite.enum}
-                                                       name={'compute/guestOS/bitSize'}
-                                                       className='radio-field'
-                                                       value={onSite.enum}
-                                                       label={onSite.title}
-                                                       onChange={(site) => onQDataChanged({'storage/backup/backupType' :  site})}
-                                                       isValid={qgenericFieldInfo['storage/backup/backupType'].isValid}
-                                                       errorText={qgenericFieldInfo['storage/backup/backupType'].errorText}
-                                                       checked={dataMap['storage/backup/backupType'] === onSite.enum} /> )) }
-                               </div>
-                       </div>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               data-test-id='backupSolution'
-                               onChange={(backupSolution) => onQDataChanged({'storage/backup/backupSolution' : backupSolution})}
-                               label={i18n('Backup Solution')}
-                               type='text'
-                               isValid={qgenericFieldInfo['storage/backup/backupSolution'].isValid}
-                               errorText={qgenericFieldInfo['storage/backup/backupSolution'].errorText}
-                               value={dataMap['storage/backup/backupSolution']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               data-test-id='backupStorageSize'
-                               onChange={(backupStorageSize) => onQDataChanged({'storage/backup/backupStorageSize' : backupStorageSize})}
-                               label={i18n('Backup Storage Size (GB)')}
-                               type='number'
-                               isValid={qgenericFieldInfo['storage/backup/backupStorageSize'].isValid}
-                               errorText={qgenericFieldInfo['storage/backup/backupStorageSize'].errorText}
-                               value={dataMap['storage/backup/backupStorageSize']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='backupNIC'
-                               label={i18n('Backup NIC')}
-                               type='select'
-                               className='input-options-select section-field'
-                               groupClassName='bootstrap-input-options'
-                               isValid={qgenericFieldInfo['storage/backup/backupNIC'].isValid}
-                               errorText={qgenericFieldInfo['storage/backup/backupNIC'].errorText}
-                               value={dataMap['storage/backup/backupNIC']}
-                               onChange={(e) => {
-                                       const selectedIndex = e.target.selectedIndex;
-                                       const val = e.target.options[selectedIndex].value;
-                                       onQDataChanged({'storage/backup/backupNIC' : val});}
-                               }>
-                               <option key='placeholder' value=''>{i18n('Select...')}</option>
-                               {qgenericFieldInfo['storage/backup/backupNIC'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
-                       </Input>
-               </GridItem>
-       </GridSection>
+const BackupSection = ({
+    isReadOnlyMode,
+    dataMap,
+    onQDataChanged,
+    qgenericFieldInfo
+}) => (
+    <GridSection title={i18n('Backup')}>
+        <GridItem>
+            <div className="vertical-flex">
+                <label
+                    key="label"
+                    className={classnames('control-label', {
+                        disabled: isReadOnlyMode
+                    })}>
+                    {i18n('Backup Type')}
+                </label>
+                <div className="radio-options-content-row">
+                    {qgenericFieldInfo['storage/backup/backupType'].enum.map(
+                        onSite => (
+                            <Input
+                                data-test-id="backupType"
+                                type="radio"
+                                key={onSite.enum}
+                                name={'compute/guestOS/bitSize'}
+                                className="radio-field"
+                                value={onSite.enum}
+                                label={onSite.title}
+                                onChange={site =>
+                                    onQDataChanged({
+                                        'storage/backup/backupType': site
+                                    })
+                                }
+                                isValid={
+                                    qgenericFieldInfo[
+                                        'storage/backup/backupType'
+                                    ].isValid
+                                }
+                                errorText={
+                                    qgenericFieldInfo[
+                                        'storage/backup/backupType'
+                                    ].errorText
+                                }
+                                checked={
+                                    dataMap['storage/backup/backupType'] ===
+                                    onSite.enum
+                                }
+                            />
+                        )
+                    )}
+                </div>
+            </div>
+        </GridItem>
+        <GridItem>
+            <Input
+                className="section-field"
+                data-test-id="backupSolution"
+                onChange={backupSolution =>
+                    onQDataChanged({
+                        'storage/backup/backupSolution': backupSolution
+                    })
+                }
+                label={i18n('Backup Solution')}
+                type="text"
+                isValid={
+                    qgenericFieldInfo['storage/backup/backupSolution'].isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/backup/backupSolution'].errorText
+                }
+                value={dataMap['storage/backup/backupSolution']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                className="section-field"
+                data-test-id="backupStorageSize"
+                onChange={backupStorageSize =>
+                    onQDataChanged({
+                        'storage/backup/backupStorageSize': backupStorageSize
+                    })
+                }
+                label={i18n('Backup Storage Size (GB)')}
+                type="number"
+                isValid={
+                    qgenericFieldInfo['storage/backup/backupStorageSize']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/backup/backupStorageSize']
+                        .errorText
+                }
+                value={dataMap['storage/backup/backupStorageSize']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="backupNIC"
+                label={i18n('Backup NIC')}
+                type="select"
+                className="input-options-select section-field"
+                groupClassName="bootstrap-input-options"
+                isValid={qgenericFieldInfo['storage/backup/backupNIC'].isValid}
+                errorText={
+                    qgenericFieldInfo['storage/backup/backupNIC'].errorText
+                }
+                value={dataMap['storage/backup/backupNIC']}
+                onChange={e => {
+                    const selectedIndex = e.target.selectedIndex;
+                    const val = e.target.options[selectedIndex].value;
+                    onQDataChanged({ 'storage/backup/backupNIC': val });
+                }}>
+                <option key="placeholder" value="">
+                    {i18n('Select...')}
+                </option>
+                {qgenericFieldInfo['storage/backup/backupNIC'].enum.map(hv => (
+                    <option value={hv.enum} key={hv.enum}>
+                        {hv.title}
+                    </option>
+                ))}
+            </Input>
+        </GridItem>
+    </GridSection>
 );
 
-const SnapshotBackupSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Snapshot Backup')}>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               data-test-id='snapshotFrequency'
-                               onChange={(snapshotFrequency) => onQDataChanged({'storage/snapshotBackup/snapshotFrequency' : snapshotFrequency})}
-                               label={i18n('Backup Storage Size (GB)')}
-                               type='number'
-                               isValid={qgenericFieldInfo['storage/snapshotBackup/snapshotFrequency'].isValid}
-                               errorText={qgenericFieldInfo['storage/snapshotBackup/snapshotFrequency'].errorText}
-                               value={dataMap['storage/snapshotBackup/snapshotFrequency']}/>
-               </GridItem>
-       </GridSection>
+const SnapshotBackupSection = ({
+    dataMap,
+    onQDataChanged,
+    qgenericFieldInfo
+}) => (
+    <GridSection title={i18n('Snapshot Backup')}>
+        <GridItem>
+            <Input
+                className="section-field"
+                data-test-id="snapshotFrequency"
+                onChange={snapshotFrequency =>
+                    onQDataChanged({
+                        'storage/snapshotBackup/snapshotFrequency': snapshotFrequency
+                    })
+                }
+                label={i18n('Backup Storage Size (GB)')}
+                type="number"
+                isValid={
+                    qgenericFieldInfo[
+                        'storage/snapshotBackup/snapshotFrequency'
+                    ].isValid
+                }
+                errorText={
+                    qgenericFieldInfo[
+                        'storage/snapshotBackup/snapshotFrequency'
+                    ].errorText
+                }
+                value={dataMap['storage/snapshotBackup/snapshotFrequency']}
+            />
+        </GridItem>
+    </GridSection>
 );
 
-const LogBackupSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
-       <GridSection title={i18n('Log Backup')}>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               data-test-id='sizeOfLogFiles'
-                               onChange={(sizeOfLogFiles) => onQDataChanged({'storage/logBackup/sizeOfLogFiles' : sizeOfLogFiles})}
-                               label={i18n('Backup Storage Size (GB)')}
-                               type='number'
-                               isValid={qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'].isValid}
-                               errorText={qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'].errorText}
-                               value={dataMap['storage/logBackup/sizeOfLogFiles']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               label={i18n('Log Retention Period (days)')}
-                               data-test-id='logRetentionPeriod'
-                               onChange={(logRetentionPeriod) => onQDataChanged({'storage/logBackup/logRetentionPeriod' : logRetentionPeriod})}
-                               type='number'
-                               isValid={qgenericFieldInfo['storage/logBackup/logRetentionPeriod'].isValid}
-                               errorText={qgenericFieldInfo['storage/logBackup/logRetentionPeriod'].errorText}
-                               value={dataMap['storage/logBackup/logRetentionPeriod']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               label={i18n('Log Backup Frequency (days)')}
-                               data-test-id='logBackupFrequency'
-                               onChange={(logBackupFrequency) => onQDataChanged({'storage/logBackup/logBackupFrequency' : logBackupFrequency})}
-                               type='number'
-                               isValid={qgenericFieldInfo['storage/logBackup/logBackupFrequency'].isValid}
-                               errorText={qgenericFieldInfo['storage/logBackup/logBackupFrequency'].errorText}
-                               value={dataMap['storage/logBackup/logBackupFrequency']}/>
-               </GridItem>
-               <GridItem>
-                       <Input
-                               className='section-field'
-                               label={i18n('Log File Location')}
-                               data-test-id='logFileLocation'
-                               onChange={(logFileLocation) => onQDataChanged({'storage/logBackup/logFileLocation' : logFileLocation})}
-                               type='text'
-                               isValid={qgenericFieldInfo['storage/logBackup/logFileLocation'].isValid}
-                               errorText={qgenericFieldInfo['storage/logBackup/logFileLocation'].errorText}
-                               value={dataMap['storage/logBackup/logFileLocation']}/>
-               </GridItem>
-       </GridSection>
+const LogBackupSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => (
+    <GridSection title={i18n('Log Backup')}>
+        <GridItem>
+            <Input
+                className="section-field"
+                data-test-id="sizeOfLogFiles"
+                onChange={sizeOfLogFiles =>
+                    onQDataChanged({
+                        'storage/logBackup/sizeOfLogFiles': sizeOfLogFiles
+                    })
+                }
+                label={i18n('Backup Storage Size (GB)')}
+                type="number"
+                isValid={
+                    qgenericFieldInfo['storage/logBackup/sizeOfLogFiles']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/logBackup/sizeOfLogFiles']
+                        .errorText
+                }
+                value={dataMap['storage/logBackup/sizeOfLogFiles']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                className="section-field"
+                label={i18n('Log Retention Period (days)')}
+                data-test-id="logRetentionPeriod"
+                onChange={logRetentionPeriod =>
+                    onQDataChanged({
+                        'storage/logBackup/logRetentionPeriod': logRetentionPeriod
+                    })
+                }
+                type="number"
+                isValid={
+                    qgenericFieldInfo['storage/logBackup/logRetentionPeriod']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/logBackup/logRetentionPeriod']
+                        .errorText
+                }
+                value={dataMap['storage/logBackup/logRetentionPeriod']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                className="section-field"
+                label={i18n('Log Backup Frequency (days)')}
+                data-test-id="logBackupFrequency"
+                onChange={logBackupFrequency =>
+                    onQDataChanged({
+                        'storage/logBackup/logBackupFrequency': logBackupFrequency
+                    })
+                }
+                type="number"
+                isValid={
+                    qgenericFieldInfo['storage/logBackup/logBackupFrequency']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/logBackup/logBackupFrequency']
+                        .errorText
+                }
+                value={dataMap['storage/logBackup/logBackupFrequency']}
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                className="section-field"
+                label={i18n('Log File Location')}
+                data-test-id="logFileLocation"
+                onChange={logFileLocation =>
+                    onQDataChanged({
+                        'storage/logBackup/logFileLocation': logFileLocation
+                    })
+                }
+                type="text"
+                isValid={
+                    qgenericFieldInfo['storage/logBackup/logFileLocation']
+                        .isValid
+                }
+                errorText={
+                    qgenericFieldInfo['storage/logBackup/logFileLocation']
+                        .errorText
+                }
+                value={dataMap['storage/logBackup/logFileLocation']}
+            />
+        </GridItem>
+    </GridSection>
 );
 
 class SoftwareProductComponentStorageView extends React.Component {
+    static propTypes = {
+        componentId: PropTypes.string,
+        onQDataChanged: PropTypes.func,
+        onSubmit: PropTypes.func,
+        isReadOnlyMode: PropTypes.bool
+    };
 
-       static propTypes = {
-               componentId: PropTypes.string,
-               onQDataChanged: PropTypes.func,
-               onSubmit: PropTypes.func,
-               isReadOnlyMode: PropTypes.bool
-       };
+    render() {
+        let {
+            onQDataChanged,
+            dataMap,
+            qGenericFieldInfo,
+            isReadOnlyMode,
+            onSubmit,
+            qdata
+        } = this.props;
 
-       render() {
-               let {onQDataChanged, dataMap, qGenericFieldInfo, isReadOnlyMode, onSubmit, qdata} =  this.props;
+        return (
+            <div className="vsp-component-questionnaire-view">
+                {qGenericFieldInfo && (
+                    <Form
+                        ref={form => (this.form = form)}
+                        isValid={true}
+                        formReady={null}
+                        onSubmit={() => onSubmit({ qdata })}
+                        className="component-questionnaire-validation-form"
+                        isReadOnlyMode={isReadOnlyMode}
+                        hasButtons={false}>
+                        <BackupSection
+                            isReadOnlyMode={isReadOnlyMode}
+                            onQDataChanged={onQDataChanged}
+                            dataMap={dataMap}
+                            qgenericFieldInfo={qGenericFieldInfo}
+                        />
+                        <SnapshotBackupSection
+                            onQDataChanged={onQDataChanged}
+                            dataMap={dataMap}
+                            qgenericFieldInfo={qGenericFieldInfo}
+                        />
+                        <LogBackupSection
+                            onQDataChanged={onQDataChanged}
+                            dataMap={dataMap}
+                            qgenericFieldInfo={qGenericFieldInfo}
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-               return(
-                       <div className='vsp-component-questionnaire-view'>
-                               {qGenericFieldInfo && <Form
-                                       ref={form => this.form = form }
-                                       isValid={true}
-                                       formReady={null}
-                                       onSubmit={() => onSubmit({qdata})}
-                                       className='component-questionnaire-validation-form'
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       hasButtons={false}>
-                                       <BackupSection isReadOnlyMode={isReadOnlyMode} onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                       <SnapshotBackupSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                                       <LogBackupSection  onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
-                               </Form> }
-                       </div>
-               );
-       }
-
-       save(){         
-               const {qdata, onSubmit} = this.props;
-               return onSubmit({qdata});
-       }
+    save() {
+        const { qdata, onSubmit } = this.props;
+        return onSubmit({ qdata });
+    }
 }
 
 export default SoftwareProductComponentStorageView;
index 569b33f..41584d9 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import SoftwareProductCreationActionHelper from './SoftwareProductCreationActionHelper.js';
 import SoftwareProductCreationView from './SoftwareProductCreationView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import SoftwareProductActionHelper  from '../SoftwareProductActionHelper.js';
+import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import {itemTypes as versionItemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
+import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
 
-export const mapStateToProps = ({finalizedLicenseModelList, users: {usersList}, archivedSoftwareProductList, 
-               softwareProductList, finalizedSoftwareProductList, softwareProduct: {softwareProductCreation, softwareProductCategories} }) => {
-       let {genericFieldInfo} = softwareProductCreation;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+export const mapStateToProps = ({
+    finalizedLicenseModelList,
+    users: { usersList },
+    archivedSoftwareProductList,
+    softwareProductList,
+    finalizedSoftwareProductList,
+    softwareProduct: { softwareProductCreation, softwareProductCategories }
+}) => {
+    let { genericFieldInfo } = softwareProductCreation;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       let VSPNames = {};
-       const allVspList = [...softwareProductList, ...finalizedSoftwareProductList, ...archivedSoftwareProductList];
-       allVspList.map(item => {
-               VSPNames[item.name.toLowerCase()] = item.id;
-       });
-       
+    let VSPNames = {};
+    const allVspList = [
+        ...softwareProductList,
+        ...finalizedSoftwareProductList,
+        ...archivedSoftwareProductList
+    ];
+    allVspList.map(item => {
+        VSPNames[item.name.toLowerCase()] = item.id;
+    });
 
-       return {
-               data: softwareProductCreation.data,
-               selectedVendorId: softwareProductCreation.selectedVendorId,
-               disableVendor: softwareProductCreation.disableVendor,
-               softwareProductCategories,
-               finalizedLicenseModelList,
-               isFormValid,
-               formReady: softwareProductCreation.formReady,
-               genericFieldInfo,
-               VSPNames,
-               usersList
-       };
+    return {
+        data: softwareProductCreation.data,
+        selectedVendorId: softwareProductCreation.selectedVendorId,
+        disableVendor: softwareProductCreation.disableVendor,
+        softwareProductCategories,
+        finalizedLicenseModelList,
+        isFormValid,
+        formReady: softwareProductCreation.formReady,
+        genericFieldInfo,
+        VSPNames,
+        usersList
+    };
 };
 
-export const mapActionsToProps = (dispatch) => {
-       return {
-               onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
-               onCancel: () => SoftwareProductCreationActionHelper.resetData(dispatch),
-               onSubmit: (softwareProduct, usersList) => {
-                       SoftwareProductCreationActionHelper.resetData(dispatch);
-                       SoftwareProductCreationActionHelper.createSoftwareProduct(dispatch, {softwareProduct}).then(response => {
-                               let {itemId, version} = response;
-                               SoftwareProductActionHelper.fetchSoftwareProductList(dispatch).then(() =>
-                                       PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers: usersList}).then(() =>
-                                               VersionsPageActionHelper.fetchVersions(dispatch, {itemType: versionItemTypes.SOFTWARE_PRODUCT, itemId}).then(() =>
-                                                       ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
-                                                               props: {softwareProductId: itemId, version}})
-                                               )
-                                       )
-                               );
-                       });
-               },
-               onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
-       };
+export const mapActionsToProps = dispatch => {
+    return {
+        onDataChanged: (deltaData, formName, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName,
+                customValidations
+            }),
+        onCancel: () => SoftwareProductCreationActionHelper.resetData(dispatch),
+        onSubmit: (softwareProduct, usersList) => {
+            SoftwareProductCreationActionHelper.resetData(dispatch);
+            SoftwareProductCreationActionHelper.createSoftwareProduct(
+                dispatch,
+                { softwareProduct }
+            ).then(response => {
+                let { itemId, version } = response;
+                SoftwareProductActionHelper.fetchSoftwareProductList(
+                    dispatch
+                ).then(() =>
+                    PermissionsActionHelper.fetchItemUsers(dispatch, {
+                        itemId,
+                        allUsers: usersList
+                    }).then(() =>
+                        VersionsPageActionHelper.fetchVersions(dispatch, {
+                            itemType: versionItemTypes.SOFTWARE_PRODUCT,
+                            itemId
+                        }).then(() =>
+                            ScreensHelper.loadScreen(dispatch, {
+                                screen:
+                                    enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
+                                screenType: screenTypes.SOFTWARE_PRODUCT,
+                                props: { softwareProductId: itemId, version }
+                            })
+                        )
+                    )
+                );
+            });
+        },
+        onValidateForm: formName =>
+            ValidationHelper.validateForm(dispatch, formName)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductCreationView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductCreationView);
index b19e460..1b1fd71 100644 (file)
@@ -17,68 +17,68 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
-import {actionTypes as modalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {actionTypes} from './SoftwareProductCreationConstants.js';
+import {
+    actionTypes as modalActionTypes,
+    modalSizes
+} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes } from './SoftwareProductCreationConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/`;
 }
 
 function createSoftwareProduct(softwareProduct) {
-       return RestAPIUtil.post(baseUrl(), {
-               ...softwareProduct,
-               icon: 'icon',
-               licensingData: {}
-       });
+    return RestAPIUtil.post(baseUrl(), {
+        ...softwareProduct,
+        icon: 'icon',
+        licensingData: {}
+    });
 }
 
 const SoftwareProductCreationActionHelper = {
+    open(dispatch, vendorId) {
+        SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
+        dispatch({
+            type: actionTypes.OPEN,
+            selectedVendorId: vendorId
+        });
 
-       open(dispatch, vendorId) {
-               SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
-               dispatch({
-                       type: actionTypes.OPEN,
-                       selectedVendorId: vendorId
-               });
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName:
+                    modalContentMapper.SOFTWARE_PRODUCT_CREATION,
+                title: i18n('New Software Product'),
+                modalComponentProps: {
+                    vendorId,
+                    size: modalSizes.LARGE
+                }
+            }
+        });
+    },
 
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_CREATION,
-                               title: i18n('New Software Product'),
-                               modalComponentProps: {
-                                       vendorId,
-                                       size: modalSizes.LARGE
-                               }
-                       }
-               });
+    resetData(dispatch) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
 
-       },
-
-       resetData(dispatch) {
-
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-
-               dispatch({
-                       type: actionTypes.RESET_DATA
-               });
-       },
-
-       createSoftwareProduct(dispatch, {softwareProduct}) {
-               return createSoftwareProduct(softwareProduct).then(result => {
-                       dispatch({
-                               type: actionTypes.SOFTWARE_PRODUCT_CREATED,
-                               result
-                       });
-                       return result;
-               });
-       }
+        dispatch({
+            type: actionTypes.RESET_DATA
+        });
+    },
 
+    createSoftwareProduct(dispatch, { softwareProduct }) {
+        return createSoftwareProduct(softwareProduct).then(result => {
+            dispatch({
+                type: actionTypes.SOFTWARE_PRODUCT_CREATED,
+                result
+            });
+            return result;
+        });
+    }
 };
 
 export default SoftwareProductCreationActionHelper;
index b941c84..ad10346 100644 (file)
@@ -16,9 +16,9 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       OPEN: null,
-       RESET_DATA: null,
-       SOFTWARE_PRODUCT_CREATED: null
+    OPEN: null,
+    RESET_DATA: null,
+    SOFTWARE_PRODUCT_CREATED: null
 });
 
 export const SP_CREATION_FORM_NAME = 'SPCREATIONFORM';
index a7db2b2..5f70f18 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, SP_CREATION_FORM_NAME} from './SoftwareProductCreationConstants.js';
-
+import {
+    actionTypes,
+    SP_CREATION_FORM_NAME
+} from './SoftwareProductCreationConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.OPEN:
-                       return {
-                               ...state,
-                               formName: SP_CREATION_FORM_NAME,
-                               disableVendor: action.selectedVendorId ? true : false,
-                               data: {
-                                       vendorId: action.selectedVendorId ? action.selectedVendorId : undefined
-                               },
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'freeEnglishText', data: true}, {type: 'maxLength', data: 1000}, {type: 'required', data: true}]
-                                       },
-                                       'vendorId' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       'subCategory' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       'category' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       },
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}, {type: 'validateName', data: true}]
-                                       },
-                                       'onboardingMethod' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'requiredChooseOption', data: true}]
-                                       }
-                               },
-                               showModal: true
-                       };
-               case actionTypes.RESET_DATA:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.OPEN:
+            return {
+                ...state,
+                formName: SP_CREATION_FORM_NAME,
+                disableVendor: action.selectedVendorId ? true : false,
+                data: {
+                    vendorId: action.selectedVendorId
+                        ? action.selectedVendorId
+                        : undefined
+                },
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'freeEnglishText', data: true },
+                            { type: 'maxLength', data: 1000 },
+                            { type: 'required', data: true }
+                        ]
+                    },
+                    vendorId: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    subCategory: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    category: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    },
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 25 },
+                            { type: 'validateName', data: true }
+                        ]
+                    },
+                    onboardingMethod: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'requiredChooseOption', data: true }
+                        ]
+                    }
+                },
+                showModal: true
+            };
+        case actionTypes.RESET_DATA:
+            return {};
+        default:
+            return state;
+    }
 };
index e491491..e94087c 100644 (file)
@@ -22,194 +22,308 @@ import Form from 'nfvo-components/input/validation/Form.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
-import {SP_CREATION_FORM_NAME} from './SoftwareProductCreationConstants.js';
+import { SP_CREATION_FORM_NAME } from './SoftwareProductCreationConstants.js';
 import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
 
 import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
-import {onboardingMethod as onboardingMethodConst} from '../SoftwareProductConstants.js';
+import { onboardingMethod as onboardingMethodConst } from '../SoftwareProductConstants.js';
 
 const SoftwareProductPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       category: PropTypes.string,
-       subCategory: PropTypes.string,
-       vendorId: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    category: PropTypes.string,
+    subCategory: PropTypes.string,
+    vendorId: PropTypes.string
 });
 
 class SoftwareProductCreationView extends React.Component {
+    static propTypes = {
+        data: SoftwareProductPropType,
+        finalizedLicenseModelList: PropTypes.array,
+        softwareProductCategories: PropTypes.array,
+        VSPNames: PropTypes.object,
+        usersList: PropTypes.array,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               data: SoftwareProductPropType,
-               finalizedLicenseModelList: PropTypes.array,
-               softwareProductCategories: PropTypes.array,
-               VSPNames: PropTypes.object,
-               usersList: PropTypes.array,
-               onDataChanged: PropTypes.func.isRequired,
-               onSubmit: PropTypes.func.isRequired,
-               onCancel: PropTypes.func.isRequired
-       };
-
-       render() {
-               let {softwareProductCategories, data = {}, onDataChanged, onCancel, genericFieldInfo, disableVendor} = this.props;
-               let {name, description, vendorId, subCategory, onboardingMethod} = data;
-
-               const vendorList = this.getVendorList();
-               return (
-                       <div className='software-product-creation-page'>
-                               { genericFieldInfo && <Form
-                                       ref={(validationForm) => this.validationForm = validationForm}
-                                       hasButtons={true}
-                                       onSubmit={() => this.submit() }
-                                       onReset={() => onCancel() }
-                                       labledButtons={true}
-                                       isValid={this.props.isFormValid}
-                                       submitButtonText={i18n('Create')}
-                                       formReady={this.props.formReady}
-                                       onValidateForm={() => this.validate() }>
-                                       <GridSection hasLastColSet>
-                                               <GridItem colSpan='2'>
-                                                       <Input
-                                                               value={name}
-                                                               label={i18n('Name')}
-                                                               isRequired={true}
-                                                               onChange={name => onDataChanged({name},SP_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}
-                                                               overlayPos='bottom'
-                                                               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>
-                                               </GridItem>
-                                               <GridItem colSpan='2' stretch lastColInRow>
-                                                       <Input
-                                                               value={description}
-                                                               label={i18n('Description')}
-                                                               isRequired={true}
-                                                               overlayPos='bottom'
-                                                               onChange={description => onDataChanged({description},SP_CREATION_FORM_NAME)}
-                                                               isValid={genericFieldInfo.description.isValid}
-                                                               errorText={genericFieldInfo.description.errorText}
-                                                               type='textarea'
-                                                               className='field-section'
-                                                               data-test-id='new-vsp-description'/>
-                                               </GridItem>
-                                       </GridSection>
-                                       <OnboardingProcedure genericFieldInfo={genericFieldInfo} onboardingMethod={onboardingMethod} onDataChanged={onDataChanged} />
-                               </Form>}
-                       </div>
-               );
-       }
-
-       getVendorList() {
-               let {finalizedLicenseModelList} =  this.props;
-
-               return [{enum: '', title: i18n('please select...')}].concat(
-                       sortByStringProperty(finalizedLicenseModelList, 'name').map(vendor => {
-                               return {
-                                       enum: vendor.id,
-                                       title: vendor.name
-                               };
-                       })
-               );
-       }
-
-       onSelectVendor(e) {
-               const selectedIndex = e.target.selectedIndex;
-               const vendorId = e.target.options[selectedIndex].value;
-               this.props.onDataChanged({vendorId},SP_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},SP_CREATION_FORM_NAME);
-       }
-
-       submit() {
-               let  {data:softwareProduct, finalizedLicenseModelList, usersList} = this.props;
-               softwareProduct.vendorName = finalizedLicenseModelList.find(vendor => vendor.id === softwareProduct.vendorId).name;
-               this.props.onSubmit(softwareProduct, usersList);
-       }
-
-       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);
-       }
+    render() {
+        let {
+            softwareProductCategories,
+            data = {},
+            onDataChanged,
+            onCancel,
+            genericFieldInfo,
+            disableVendor
+        } = this.props;
+        let {
+            name,
+            description,
+            vendorId,
+            subCategory,
+            onboardingMethod
+        } = data;
+
+        const vendorList = this.getVendorList();
+        return (
+            <div className="software-product-creation-page">
+                {genericFieldInfo && (
+                    <Form
+                        ref={validationForm =>
+                            (this.validationForm = validationForm)
+                        }
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        labledButtons={true}
+                        isValid={this.props.isFormValid}
+                        submitButtonText={i18n('Create')}
+                        formReady={this.props.formReady}
+                        onValidateForm={() => this.validate()}>
+                        <GridSection hasLastColSet>
+                            <GridItem colSpan="2">
+                                <Input
+                                    value={name}
+                                    label={i18n('Name')}
+                                    isRequired={true}
+                                    onChange={name =>
+                                        onDataChanged(
+                                            { name },
+                                            SP_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}
+                                    overlayPos="bottom"
+                                    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>
+                            </GridItem>
+                            <GridItem colSpan="2" stretch lastColInRow>
+                                <Input
+                                    value={description}
+                                    label={i18n('Description')}
+                                    isRequired={true}
+                                    overlayPos="bottom"
+                                    onChange={description =>
+                                        onDataChanged(
+                                            { description },
+                                            SP_CREATION_FORM_NAME
+                                        )
+                                    }
+                                    isValid={
+                                        genericFieldInfo.description.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.description.errorText
+                                    }
+                                    type="textarea"
+                                    className="field-section"
+                                    data-test-id="new-vsp-description"
+                                />
+                            </GridItem>
+                        </GridSection>
+                        <OnboardingProcedure
+                            genericFieldInfo={genericFieldInfo}
+                            onboardingMethod={onboardingMethod}
+                            onDataChanged={onDataChanged}
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
+
+    getVendorList() {
+        let { finalizedLicenseModelList } = this.props;
+
+        return [{ enum: '', title: i18n('please select...') }].concat(
+            sortByStringProperty(finalizedLicenseModelList, 'name').map(
+                vendor => {
+                    return {
+                        enum: vendor.id,
+                        title: vendor.name
+                    };
+                }
+            )
+        );
+    }
+
+    onSelectVendor(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const vendorId = e.target.options[selectedIndex].value;
+        this.props.onDataChanged({ vendorId }, SP_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 }, SP_CREATION_FORM_NAME);
+    }
+
+    submit() {
+        let {
+            data: softwareProduct,
+            finalizedLicenseModelList,
+            usersList
+        } = this.props;
+        softwareProduct.vendorName = finalizedLicenseModelList.find(
+            vendor => vendor.id === softwareProduct.vendorId
+        ).name;
+        this.props.onSubmit(softwareProduct, usersList);
+    }
+
+    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);
+    }
 }
 
-const OnboardingProcedure = ({onboardingMethod, onDataChanged, genericFieldInfo}) => {
-       return(
-               <GridSection title={i18n('Onboarding procedure')}>
-                       <GridItem colSpan={4}>
-                               <Input
-                                       label={i18n('Network Package')}
-                                       overlayPos='top'
-                                       isValid={genericFieldInfo.onboardingMethod.isValid}
-                                       checked={onboardingMethod === onboardingMethodConst.NETWORK_PACKAGE}
-                                       errorText={genericFieldInfo.onboardingMethod.errorText}
-                                       onChange={() => onDataChanged({onboardingMethod: onboardingMethodConst.NETWORK_PACKAGE},SP_CREATION_FORM_NAME)}
-                                       type='radio'
-                                       data-test-id='new-vsp-creation-procedure-heat' />
-                       </GridItem>
-                       <GridItem colSpan={4}>
-                               <Input
-                                       label={i18n('Manual')}
-                                       overlayPos='bottom'
-                                       checked={onboardingMethod === onboardingMethodConst.MANUAL}
-                                       isValid={genericFieldInfo.onboardingMethod.isValid}
-                                       errorText={genericFieldInfo.onboardingMethod.errorText}
-                                       onChange={() => onDataChanged({onboardingMethod: onboardingMethodConst.MANUAL},SP_CREATION_FORM_NAME)}
-                                       type='radio'
-                                       data-test-id='new-vsp-creation-procedure-manual' />
-                       </GridItem>
-               </GridSection>
-       );
+const OnboardingProcedure = ({
+    onboardingMethod,
+    onDataChanged,
+    genericFieldInfo
+}) => {
+    return (
+        <GridSection title={i18n('Onboarding procedure')}>
+            <GridItem colSpan={4}>
+                <Input
+                    label={i18n('Network Package')}
+                    overlayPos="top"
+                    isValid={genericFieldInfo.onboardingMethod.isValid}
+                    checked={
+                        onboardingMethod ===
+                        onboardingMethodConst.NETWORK_PACKAGE
+                    }
+                    errorText={genericFieldInfo.onboardingMethod.errorText}
+                    onChange={() =>
+                        onDataChanged(
+                            {
+                                onboardingMethod:
+                                    onboardingMethodConst.NETWORK_PACKAGE
+                            },
+                            SP_CREATION_FORM_NAME
+                        )
+                    }
+                    type="radio"
+                    data-test-id="new-vsp-creation-procedure-heat"
+                />
+            </GridItem>
+            <GridItem colSpan={4}>
+                <Input
+                    label={i18n('Manual')}
+                    overlayPos="bottom"
+                    checked={onboardingMethod === onboardingMethodConst.MANUAL}
+                    isValid={genericFieldInfo.onboardingMethod.isValid}
+                    errorText={genericFieldInfo.onboardingMethod.errorText}
+                    onChange={() =>
+                        onDataChanged(
+                            { onboardingMethod: onboardingMethodConst.MANUAL },
+                            SP_CREATION_FORM_NAME
+                        )
+                    }
+                    type="radio"
+                    data-test-id="new-vsp-creation-procedure-manual"
+                />
+            </GridItem>
+        </GridSection>
+    );
 };
 
 export default SoftwareProductCreationView;
index 9888087..1a0c66d 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 
 import SoftwareProductDependenciesView from './SoftwareProductDependenciesView.jsx';
 import SoftwareProductDependenciesActionHelper from './SoftwareProductDependenciesActionHelper.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductDependencies, softwareProductComponents: {componentsList}} = softwareProduct;
-       return {
-               softwareProductDependencies: softwareProductDependencies,
-               componentsOptions: componentsList.map(component => ({value: component.id, label: component.displayName}))
-       };
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductDependencies,
+        softwareProductComponents: { componentsList }
+    } = softwareProduct;
+    return {
+        softwareProductDependencies: softwareProductDependencies,
+        componentsOptions: componentsList.map(component => ({
+            value: component.id,
+            label: component.displayName
+        }))
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onDataChanged: (item) => SoftwareProductDependenciesActionHelper.updateDependency(dispatch, {softwareProductId, version, item}),
-               onDeleteDependency: (item) => SoftwareProductDependenciesActionHelper.removeDependency(dispatch, {softwareProductId, version, item}),
-               onAddDependency: (item) => SoftwareProductDependenciesActionHelper.createDependency(dispatch, {softwareProductId, version, item})
-       };
+const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onDataChanged: item =>
+            SoftwareProductDependenciesActionHelper.updateDependency(dispatch, {
+                softwareProductId,
+                version,
+                item
+            }),
+        onDeleteDependency: item =>
+            SoftwareProductDependenciesActionHelper.removeDependency(dispatch, {
+                softwareProductId,
+                version,
+                item
+            }),
+        onAddDependency: item =>
+            SoftwareProductDependenciesActionHelper.createDependency(dispatch, {
+                softwareProductId,
+                version,
+                item
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDependenciesView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductDependenciesView);
index f04f8fa..4bbcaa1 100644 (file)
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js';
+import {
+    actionTypes,
+    NEW_RULE_TEMP_ID
+} from './SoftwareProductDependenciesConstants.js';
 
 function baseUrl(softwareProductId, version) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependencies`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependencies`;
 }
 
 function fetchDependencies(softwareProductId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
 }
 
 function addDepencency(softwareProductId, version, item) {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
-               sourceId: item.sourceId,
-               targetId: item.targetId,
-               relationType: item.relationType
-       });
+    return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
+        sourceId: item.sourceId,
+        targetId: item.targetId,
+        relationType: item.relationType
+    });
 }
 
-
 function updateDepencency(softwareProductId, version, item) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${item.id}`,
-               {
-                       sourceId: item.sourceId,
-                       targetId: item.targetId,
-                       relationType: item.relationType
-               });
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version)}/${item.id}`,
+        {
+            sourceId: item.sourceId,
+            targetId: item.targetId,
+            relationType: item.relationType
+        }
+    );
 }
 
 function removeDependency(softwareProductId, version, item) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${item.id}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version)}/${item.id}`
+    );
 }
 
-
 const SoftwareProductDependenciesActionHelper = {
-       updateDependency(dispatch, {softwareProductId, version, item}) {
-               // if change was made on existing item - we will update the server and refresh the list
-               // if change was made on the 'new' row - we will only fire the event
-               if (item.id !== NEW_RULE_TEMP_ID) {
-                       return updateDepencency(softwareProductId, version, item).then(() => {
-                               return this.fetchDependencies(dispatch, {softwareProductId, version});
-                       });
-               } else {
-                       dispatch({
-                               type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY,
-                               item: item
-                       });
-               }
-       },
+    updateDependency(dispatch, { softwareProductId, version, item }) {
+        // if change was made on existing item - we will update the server and refresh the list
+        // if change was made on the 'new' row - we will only fire the event
+        if (item.id !== NEW_RULE_TEMP_ID) {
+            return updateDepencency(softwareProductId, version, item).then(
+                () => {
+                    return this.fetchDependencies(dispatch, {
+                        softwareProductId,
+                        version
+                    });
+                }
+            );
+        } else {
+            dispatch({
+                type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY,
+                item: item
+            });
+        }
+    },
 
-       createDependency(dispatch, {softwareProductId, version, item}) {
-               // removing the temp id
-               delete item.id;
-               // creating the new dependency
-               return addDepencency(softwareProductId, version, item).then(() => {
-                       dispatch({
-                               type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY
-                       });
-                       return this.fetchDependencies(dispatch, {softwareProductId, version});
-               });
-       },
+    createDependency(dispatch, { softwareProductId, version, item }) {
+        // removing the temp id
+        delete item.id;
+        // creating the new dependency
+        return addDepencency(softwareProductId, version, item).then(() => {
+            dispatch({
+                type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY
+            });
+            return this.fetchDependencies(dispatch, {
+                softwareProductId,
+                version
+            });
+        });
+    },
 
-       removeDependency(dispatch, {softwareProductId, version, item}) {
-               return removeDependency(softwareProductId, version, item).then( () => {
-                       return this.fetchDependencies(dispatch, {softwareProductId, version});
-               });
-       },
+    removeDependency(dispatch, { softwareProductId, version, item }) {
+        return removeDependency(softwareProductId, version, item).then(() => {
+            return this.fetchDependencies(dispatch, {
+                softwareProductId,
+                version
+            });
+        });
+    },
 
-       fetchDependencies(dispatch, {softwareProductId, version}) {
-               return fetchDependencies(softwareProductId, version).then( response => {
-                       dispatch({
-                               type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE,
-                               dependenciesList : response.results
-                       });
-               });
-       }
+    fetchDependencies(dispatch, { softwareProductId, version }) {
+        return fetchDependencies(softwareProductId, version).then(response => {
+            dispatch({
+                type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE,
+                dependenciesList: response.results
+            });
+        });
+    }
 };
 
 export default SoftwareProductDependenciesActionHelper;
index c25561d..32c7387 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null,
-       ADD_SOFTWARE_PRODUCT_DEPENDENCY: null,
-       UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null
+    SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null,
+    ADD_SOFTWARE_PRODUCT_DEPENDENCY: null,
+    UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null
 });
 
 export const relationTypes = {
-       DEPENDS_ON: 'dependsOn'
+    DEPENDS_ON: 'dependsOn'
 };
 
 export const relationTypesOptions = [
-    {value: relationTypes.DEPENDS_ON, label: 'Depends On'}
+    { value: relationTypes.DEPENDS_ON, label: 'Depends On' }
 ];
 
-export const NEW_RULE_TEMP_ID = 'newRuleTempId';
\ No newline at end of file
+export const NEW_RULE_TEMP_ID = 'newRuleTempId';
index 3edd3b8..6e028b1 100644 (file)
@@ -1,4 +1,3 @@
-
 /*!
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
  *
  * permissions and limitations under the License.
  */
 
-import {actionTypes, relationTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js';
-import {checkCyclesAndMarkDependencies} from './SoftwareProductDependenciesUtils.js';
+import {
+    actionTypes,
+    relationTypes,
+    NEW_RULE_TEMP_ID
+} from './SoftwareProductDependenciesConstants.js';
+import { checkCyclesAndMarkDependencies } from './SoftwareProductDependenciesUtils.js';
 
-let newRowObject = {id: NEW_RULE_TEMP_ID, targetId: null, sourceId: null, relationType: relationTypes.DEPENDS_ON};
+let newRowObject = {
+    id: NEW_RULE_TEMP_ID,
+    targetId: null,
+    sourceId: null,
+    relationType: relationTypes.DEPENDS_ON
+};
 
-export default (state = [Object.assign({}, newRowObject) ], action) => {
-       switch (action.type) {
-               case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE:
-                       // copying the entity with the data for the row that is in the 'add' mode
-                       let newDependency = state.find(dependency => dependency.id === NEW_RULE_TEMP_ID);
-                       action.dependenciesList.push(newDependency);
-                       // returning list from the server with our 'new entity' row
-                       return checkCyclesAndMarkDependencies(action.dependenciesList);
-               case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY :
-                       // resetting the entity with the data for the 'add' mode for a new entity
-                       let newArray = state.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID);
-                       newArray.push(Object.assign({}, newRowObject));
-                       return newArray;
-               case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY :
-                       // we really only need this for the 'new' row since we need to change the state to get
-                       // everything updated
-                       let updateArrayIndex = state.findIndex(dependency => dependency.id === NEW_RULE_TEMP_ID);
-                       let updateArray = state.slice();
-                       updateArray.splice(updateArrayIndex, 1, action.item);
-                       return checkCyclesAndMarkDependencies(updateArray);
-               default:
-                       return state;
-       }
+export default (state = [Object.assign({}, newRowObject)], action) => {
+    switch (action.type) {
+        case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE:
+            // copying the entity with the data for the row that is in the 'add' mode
+            let newDependency = state.find(
+                dependency => dependency.id === NEW_RULE_TEMP_ID
+            );
+            action.dependenciesList.push(newDependency);
+            // returning list from the server with our 'new entity' row
+            return checkCyclesAndMarkDependencies(action.dependenciesList);
+        case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY:
+            // resetting the entity with the data for the 'add' mode for a new entity
+            let newArray = state.filter(
+                dependency => dependency.id !== NEW_RULE_TEMP_ID
+            );
+            newArray.push(Object.assign({}, newRowObject));
+            return newArray;
+        case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY:
+            // we really only need this for the 'new' row since we need to change the state to get
+            // everything updated
+            let updateArrayIndex = state.findIndex(
+                dependency => dependency.id === NEW_RULE_TEMP_ID
+            );
+            let updateArray = state.slice();
+            updateArray.splice(updateArrayIndex, 1, action.item);
+            return checkCyclesAndMarkDependencies(updateArray);
+        default:
+            return state;
+    }
 };
index 94d21bd..8d5aaf8 100644 (file)
 
 import DirectedGraph from 'nfvo-utils/DirectedGraph.js';
 
-function findCycles(graph, node, id, visited = {}, visitedConnections = {}, recursionStack = {}, connectionsWithCycle = {}) {
-       visited[node] = true;
-       recursionStack[node] = true;
-       if (id) {
-               visitedConnections[id] = true;
-       }
-       for (let edge of graph.getEdges(node)) {
-               if (!visited[edge.target]) {
-                       findCycles(graph, edge.target, edge.id, visited, visitedConnections, recursionStack, connectionsWithCycle);
-               } else if (recursionStack[edge.target]) {
-                       visitedConnections[edge.id] = true;
-                       for (let connection in visitedConnections) {
-                               connectionsWithCycle[connection] = true;
-                       }
-               }
-       }
-       recursionStack[node] = false;
-       return {visitedNodes: visited, connectionsWithCycle: connectionsWithCycle};
+function findCycles(
+    graph,
+    node,
+    id,
+    visited = {},
+    visitedConnections = {},
+    recursionStack = {},
+    connectionsWithCycle = {}
+) {
+    visited[node] = true;
+    recursionStack[node] = true;
+    if (id) {
+        visitedConnections[id] = true;
+    }
+    for (let edge of graph.getEdges(node)) {
+        if (!visited[edge.target]) {
+            findCycles(
+                graph,
+                edge.target,
+                edge.id,
+                visited,
+                visitedConnections,
+                recursionStack,
+                connectionsWithCycle
+            );
+        } else if (recursionStack[edge.target]) {
+            visitedConnections[edge.id] = true;
+            for (let connection in visitedConnections) {
+                connectionsWithCycle[connection] = true;
+            }
+        }
+    }
+    recursionStack[node] = false;
+    return {
+        visitedNodes: visited,
+        connectionsWithCycle: connectionsWithCycle
+    };
 }
 
 export function checkCyclesAndMarkDependencies(dependenciesList) {
-       let overallVisitedNodes = {};
-       let overallConnectionsWithCycles = {};
+    let overallVisitedNodes = {};
+    let overallConnectionsWithCycles = {};
 
-       let g = new DirectedGraph();
-       for (let dependency of dependenciesList) {
-               if (dependency.sourceId !== null && dependency.targetId !== null) {
-                       g.addEdge(dependency.sourceId, dependency.targetId, {id: dependency.id});
-               }
-       }
+    let g = new DirectedGraph();
+    for (let dependency of dependenciesList) {
+        if (dependency.sourceId !== null && dependency.targetId !== null) {
+            g.addEdge(dependency.sourceId, dependency.targetId, {
+                id: dependency.id
+            });
+        }
+    }
 
-       for (let node in g.nodes) {
-               if (!overallVisitedNodes.node) {
-                       let {visitedNodes, connectionsWithCycle} = findCycles(g, node, undefined);
-                       overallVisitedNodes = {...overallVisitedNodes, ...visitedNodes};
-                       overallConnectionsWithCycles = {...overallConnectionsWithCycles, ...connectionsWithCycle};
-               }
-       }
-       return dependenciesList.map(dependency => (
-               {
-                       ...dependency,
-                        hasCycle: dependency.sourceId && dependency.targetId ? 
-                               overallConnectionsWithCycles.hasOwnProperty(dependency.id) 
-                                : undefined
-               }));
+    for (let node in g.nodes) {
+        if (!overallVisitedNodes.node) {
+            let { visitedNodes, connectionsWithCycle } = findCycles(
+                g,
+                node,
+                undefined
+            );
+            overallVisitedNodes = { ...overallVisitedNodes, ...visitedNodes };
+            overallConnectionsWithCycles = {
+                ...overallConnectionsWithCycles,
+                ...connectionsWithCycle
+            };
+        }
+    }
+    return dependenciesList.map(dependency => ({
+        ...dependency,
+        hasCycle:
+            dependency.sourceId && dependency.targetId
+                ? overallConnectionsWithCycles.hasOwnProperty(dependency.id)
+                : undefined
+    }));
 }
index ed92de7..3ea1f2d 100644 (file)
@@ -20,111 +20,201 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import SelectActionTable from 'nfvo-components/table/SelectActionTable.jsx';
 import SelectActionTableRow from 'nfvo-components/table/SelectActionTableRow.jsx';
 import SelectActionTableCell from 'nfvo-components/table/SelectActionTableCell.jsx';
-import {relationTypesOptions, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js';
+import {
+    relationTypesOptions,
+    NEW_RULE_TEMP_ID
+} from './SoftwareProductDependenciesConstants.js';
 
-
-const TableActionRow = ({onAction, actionIcon, showAction, dependency, sourceOptions, targetOptions, onDataChanged}) => {
-       return (
-               <SelectActionTableRow
-                       key={dependency.id}
-                       onAction={onAction}
-                       overlayMsg={i18n('There is a loop between selections')}
-                       hasError={dependency.hasCycle}
-                       hasErrorIndication
-                       showAction={showAction}
-                       actionIcon={actionIcon}>
-                       <SelectActionTableCell
-                               options={sourceOptions}
-                               selected={dependency.sourceId}
-                               placeholder={i18n('Select VFC...')}
-                               clearable={false}
-                               onChange={newVal =>  {
-                                       dependency.sourceId = newVal;
-                                       onDataChanged(dependency);
-                               }} />
-                       <SelectActionTableCell options={relationTypesOptions} selected={dependency.relationType} clearable={false}/>
-                       <SelectActionTableCell
-                               placeholder={i18n('Select VFC...')}
-                               options={targetOptions}
-                               selected={dependency.targetId}
-                               clearable={false}
-                               onChange={newVal =>  {
-                                       dependency.targetId = newVal;
-                                       onDataChanged(dependency);
-                               }} />
-               </SelectActionTableRow>
-       );
+const TableActionRow = ({
+    onAction,
+    actionIcon,
+    showAction,
+    dependency,
+    sourceOptions,
+    targetOptions,
+    onDataChanged
+}) => {
+    return (
+        <SelectActionTableRow
+            key={dependency.id}
+            onAction={onAction}
+            overlayMsg={i18n('There is a loop between selections')}
+            hasError={dependency.hasCycle}
+            hasErrorIndication
+            showAction={showAction}
+            actionIcon={actionIcon}>
+            <SelectActionTableCell
+                options={sourceOptions}
+                selected={dependency.sourceId}
+                placeholder={i18n('Select VFC...')}
+                clearable={false}
+                onChange={newVal => {
+                    dependency.sourceId = newVal;
+                    onDataChanged(dependency);
+                }}
+            />
+            <SelectActionTableCell
+                options={relationTypesOptions}
+                selected={dependency.relationType}
+                clearable={false}
+            />
+            <SelectActionTableCell
+                placeholder={i18n('Select VFC...')}
+                options={targetOptions}
+                selected={dependency.targetId}
+                clearable={false}
+                onChange={newVal => {
+                    dependency.targetId = newVal;
+                    onDataChanged(dependency);
+                }}
+            />
+        </SelectActionTableRow>
+    );
 };
 
-
 export default class SoftwareProductDependenciesView extends React.Component {
-       filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) {
-               let isInMap = sourceToTargetMapping.hasOwnProperty(selectedSourceId);
-               return componentsOptions.filter(component => {
-                       if (component.value === selectedTargetId) {
-                               return true;
-                       } else {
-                               return component.value !== selectedSourceId && (isInMap ? sourceToTargetMapping[selectedSourceId].indexOf(component.value) < 0 : true);
-                       }
-               });
-       }
-
-       filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) {
-               return componentsOptions.filter(component => {
-                       if (component.value === selectedSourceId) {
-                               return true;
-                       } else {
-                               let isInMap = sourceToTargetMapping.hasOwnProperty(component.value);
-                               return component.value !== selectedTargetId && (isInMap ? sourceToTargetMapping[component.value].indexOf(selectedTargetId) < 0 : true);
-                       }
-               });
-       }
+    filterTargets({
+        componentsOptions,
+        sourceToTargetMapping,
+        selectedSourceId,
+        selectedTargetId
+    }) {
+        let isInMap = sourceToTargetMapping.hasOwnProperty(selectedSourceId);
+        return componentsOptions.filter(component => {
+            if (component.value === selectedTargetId) {
+                return true;
+            } else {
+                return (
+                    component.value !== selectedSourceId &&
+                    (isInMap
+                        ? sourceToTargetMapping[selectedSourceId].indexOf(
+                              component.value
+                          ) < 0
+                        : true)
+                );
+            }
+        });
+    }
 
-       render() {
-               let {componentsOptions, softwareProductDependencies, onDataChanged, onAddDependency, onDeleteDependency, isReadOnlyMode} = this.props;
-               let sourceToTargetMapping = {};
-               softwareProductDependencies.map(dependency => {
-                       let isInMap = sourceToTargetMapping.hasOwnProperty(dependency.sourceId);
-                       if (dependency.targetId) {
-                               sourceToTargetMapping[dependency.sourceId] = isInMap ? [...sourceToTargetMapping[dependency.sourceId], dependency.targetId] : [dependency.targetId];
-                       }
-               });
-               let depList = softwareProductDependencies.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID);
-               let newDependency = softwareProductDependencies.find(dependency => dependency.id === NEW_RULE_TEMP_ID);
-               return (
-                       <div className='software-product-dependencies'>
-                               <div className='page-title'>{i18n('Dependencies')}</div>
-                               <SelectActionTable
-                                       columns={[i18n('Source'), i18n('Relation Type'), i18n('Target')]}
-                                       numOfIcons={2}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       {!isReadOnlyMode && <TableActionRow
-                                               key={newDependency.id}
-                                               actionIcon='plusCircle'
-                                               onAction={() => onAddDependency(newDependency)}
-                                               dependency={newDependency}
-                                               componentsOptions={componentsOptions}
-                                               sourceToTargetMapping={sourceToTargetMapping}
-                                               onDataChanged={onDataChanged}
-                                               sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})}
-                                               targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})}
-                                               showAction={newDependency.targetId !== null && newDependency.relationType !== null && newDependency.sourceId !== null}/> }
-                                       {depList.map(dependency => (
-                                               <TableActionRow
-                                                       key={dependency.id}
-                                                       actionIcon='trashO'
-                                                       onAction={() => onDeleteDependency(dependency)}
-                                                       dependency={dependency}
-                                                       componentsOptions={componentsOptions}
-                                                       sourceToTargetMapping={sourceToTargetMapping}
-                                                       sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
-                                                       targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
-                                                       onDataChanged={onDataChanged}
-                                                       showAction={true}/>
-                                       ))}
-                               </SelectActionTable>
-                       </div>
-               );
-       }
+    filterSources({
+        componentsOptions,
+        sourceToTargetMapping,
+        selectedSourceId,
+        selectedTargetId
+    }) {
+        return componentsOptions.filter(component => {
+            if (component.value === selectedSourceId) {
+                return true;
+            } else {
+                let isInMap = sourceToTargetMapping.hasOwnProperty(
+                    component.value
+                );
+                return (
+                    component.value !== selectedTargetId &&
+                    (isInMap
+                        ? sourceToTargetMapping[component.value].indexOf(
+                              selectedTargetId
+                          ) < 0
+                        : true)
+                );
+            }
+        });
+    }
 
+    render() {
+        let {
+            componentsOptions,
+            softwareProductDependencies,
+            onDataChanged,
+            onAddDependency,
+            onDeleteDependency,
+            isReadOnlyMode
+        } = this.props;
+        let sourceToTargetMapping = {};
+        softwareProductDependencies.map(dependency => {
+            let isInMap = sourceToTargetMapping.hasOwnProperty(
+                dependency.sourceId
+            );
+            if (dependency.targetId) {
+                sourceToTargetMapping[dependency.sourceId] = isInMap
+                    ? [
+                          ...sourceToTargetMapping[dependency.sourceId],
+                          dependency.targetId
+                      ]
+                    : [dependency.targetId];
+            }
+        });
+        let depList = softwareProductDependencies.filter(
+            dependency => dependency.id !== NEW_RULE_TEMP_ID
+        );
+        let newDependency = softwareProductDependencies.find(
+            dependency => dependency.id === NEW_RULE_TEMP_ID
+        );
+        return (
+            <div className="software-product-dependencies">
+                <div className="page-title">{i18n('Dependencies')}</div>
+                <SelectActionTable
+                    columns={[
+                        i18n('Source'),
+                        i18n('Relation Type'),
+                        i18n('Target')
+                    ]}
+                    numOfIcons={2}
+                    isReadOnlyMode={isReadOnlyMode}>
+                    {!isReadOnlyMode && (
+                        <TableActionRow
+                            key={newDependency.id}
+                            actionIcon="plusCircle"
+                            onAction={() => onAddDependency(newDependency)}
+                            dependency={newDependency}
+                            componentsOptions={componentsOptions}
+                            sourceToTargetMapping={sourceToTargetMapping}
+                            onDataChanged={onDataChanged}
+                            sourceOptions={this.filterSources({
+                                componentsOptions,
+                                sourceToTargetMapping,
+                                selectedSourceId: newDependency.sourceId,
+                                selectedTargetId: newDependency.targetId
+                            })}
+                            targetOptions={this.filterTargets({
+                                componentsOptions,
+                                sourceToTargetMapping,
+                                selectedSourceId: newDependency.sourceId,
+                                selectedTargetId: newDependency.targetId
+                            })}
+                            showAction={
+                                newDependency.targetId !== null &&
+                                newDependency.relationType !== null &&
+                                newDependency.sourceId !== null
+                            }
+                        />
+                    )}
+                    {depList.map(dependency => (
+                        <TableActionRow
+                            key={dependency.id}
+                            actionIcon="trashO"
+                            onAction={() => onDeleteDependency(dependency)}
+                            dependency={dependency}
+                            componentsOptions={componentsOptions}
+                            sourceToTargetMapping={sourceToTargetMapping}
+                            sourceOptions={this.filterSources({
+                                componentsOptions,
+                                sourceToTargetMapping,
+                                selectedSourceId: dependency.sourceId,
+                                selectedTargetId: dependency.targetId
+                            })}
+                            targetOptions={this.filterTargets({
+                                componentsOptions,
+                                sourceToTargetMapping,
+                                selectedSourceId: dependency.sourceId,
+                                selectedTargetId: dependency.targetId
+                            })}
+                            onDataChanged={onDataChanged}
+                            showAction={true}
+                        />
+                    ))}
+                </SelectActionTable>
+            </div>
+        );
+    }
 }
index a5c7006..4e03926 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductDeploymentView from './SoftwareProductDeploymentView.jsx';
 import SoftwareProductDeploymentActionHelper from './SoftwareProductDeploymentActionHelper.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
-export function mapStateToProps({softwareProduct}) {
-       let {softwareProductComponents: {componentsList}, softwareProductDeployment: {deploymentFlavors}} = softwareProduct;
-       return {
-               deploymentFlavors,
-               componentsList
-       };
+export function mapStateToProps({ softwareProduct }) {
+    let {
+        softwareProductComponents: { componentsList },
+        softwareProductDeployment: { deploymentFlavors }
+    } = softwareProduct;
+    return {
+        deploymentFlavors,
+        componentsList
+    };
 }
 
-function mapActionToProps(dispatch, {softwareProductId, version}) {
-       let modalClassName = 'deployment-flavor-editor';
-       return {
-               onAddDeployment: componentsList => SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor(dispatch, {softwareProductId, modalClassName, componentsList, version}),
-               onDeleteDeployment: ({id, model}) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{model}"?', {model: model}),
-                               onConfirmed: () => SoftwareProductDeploymentActionHelper.deleteDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId: id, version})
-                       }
-               }),
-               onEditDeployment: (deploymentFlavor, componentsList) =>
-                       SoftwareProductDeploymentActionHelper.fetchDeploymentFlavor({softwareProductId, deploymentFlavorId: deploymentFlavor.id, version}).then(response =>
-                               SoftwareProductDeploymentActionHelper
-                                       .openDeploymentFlavorEditor(dispatch, {softwareProductId, componentsList, modalClassName, deploymentFlavor: {...response.data, id: response.id}, isEdit: true, version}),
-                       )
-       };
+function mapActionToProps(dispatch, { softwareProductId, version }) {
+    let modalClassName = 'deployment-flavor-editor';
+    return {
+        onAddDeployment: componentsList =>
+            SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor(
+                dispatch,
+                { softwareProductId, modalClassName, componentsList, version }
+            ),
+        onDeleteDeployment: ({ id, model }) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{model}"?', {
+                        model: model
+                    }),
+                    onConfirmed: () =>
+                        SoftwareProductDeploymentActionHelper.deleteDeploymentFlavor(
+                            dispatch,
+                            {
+                                softwareProductId,
+                                deploymentFlavorId: id,
+                                version
+                            }
+                        )
+                }
+            }),
+        onEditDeployment: (deploymentFlavor, componentsList) =>
+            SoftwareProductDeploymentActionHelper.fetchDeploymentFlavor({
+                softwareProductId,
+                deploymentFlavorId: deploymentFlavor.id,
+                version
+            }).then(response =>
+                SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor(
+                    dispatch,
+                    {
+                        softwareProductId,
+                        componentsList,
+                        modalClassName,
+                        deploymentFlavor: { ...response.data, id: response.id },
+                        isEdit: true,
+                        version
+                    }
+                )
+            )
+    };
 }
 
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductDeploymentView);
+export default connect(mapStateToProps, mapActionToProps, null, {
+    withRef: true
+})(SoftwareProductDeploymentView);
index bd802b3..44b2531 100644 (file)
-import {actionTypes} from './SoftwareProductDeploymentConstants.js';
-import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import { actionTypes } from './SoftwareProductDeploymentConstants.js';
+import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import pickBy from 'lodash/pickBy';
 
 function baseUrl(vspId, version) {
-       const versionId = version.id;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/deployment-flavors`;
+    const versionId = version.id;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/deployment-flavors`;
 }
 
-function fetchDeploymentFlavorsList({softwareProductId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+function fetchDeploymentFlavorsList({ softwareProductId, version }) {
+    return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
 }
 
-function fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`);
+function fetchDeploymentFlavor({
+    softwareProductId,
+    deploymentFlavorId,
+    version
+}) {
+    return RestAPIUtil.fetch(
+        `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`
+    );
 }
 
-function deleteDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`);
+function deleteDeploymentFlavor({
+    softwareProductId,
+    deploymentFlavorId,
+    version
+}) {
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`
+    );
 }
 
-function createDeploymentFlavor({softwareProductId, data, version}) {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, data);
+function createDeploymentFlavor({ softwareProductId, data, version }) {
+    return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, data);
 }
 
-function editDeploymentFlavor({softwareProductId, deploymentFlavorId, data, version}) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`, data);
+function editDeploymentFlavor({
+    softwareProductId,
+    deploymentFlavorId,
+    data,
+    version
+}) {
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`,
+        data
+    );
 }
 
 const SoftwareProductDeploymentActionHelper = {
-       fetchDeploymentFlavorsList(dispatch, {softwareProductId, version}) {
-               return fetchDeploymentFlavorsList({softwareProductId, version}).then(response => {
-                       dispatch({
-                               type: actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS,
-                               deploymentFlavors: response.results
-                       });
-               });
-       },
+    fetchDeploymentFlavorsList(dispatch, { softwareProductId, version }) {
+        return fetchDeploymentFlavorsList({ softwareProductId, version }).then(
+            response => {
+                dispatch({
+                    type: actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS,
+                    deploymentFlavors: response.results
+                });
+            }
+        );
+    },
 
-       fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) {
-               return fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version});
-       },
+    fetchDeploymentFlavor({ softwareProductId, deploymentFlavorId, version }) {
+        return fetchDeploymentFlavor({
+            softwareProductId,
+            deploymentFlavorId,
+            version
+        });
+    },
 
-       deleteDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId, version}) {
-               return deleteDeploymentFlavor({softwareProductId, deploymentFlavorId, version}).then(() => {
-                       return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version});
-               });
-       },
+    deleteDeploymentFlavor(
+        dispatch,
+        { softwareProductId, deploymentFlavorId, version }
+    ) {
+        return deleteDeploymentFlavor({
+            softwareProductId,
+            deploymentFlavorId,
+            version
+        }).then(() => {
+            return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(
+                dispatch,
+                { softwareProductId, version }
+            );
+        });
+    },
 
-       createDeploymentFlavor(dispatch, {softwareProductId, data, version}) {
-               return createDeploymentFlavor({softwareProductId, data, version}).then(() => {
-                       return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version});
-               });
-       },
+    createDeploymentFlavor(dispatch, { softwareProductId, data, version }) {
+        return createDeploymentFlavor({
+            softwareProductId,
+            data,
+            version
+        }).then(() => {
+            return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(
+                dispatch,
+                { softwareProductId, version }
+            );
+        });
+    },
 
-       editDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId, data, version}) {
-               let dataWithoutId = pickBy(data, (val, key) => key !== 'id');
-               return editDeploymentFlavor({softwareProductId, deploymentFlavorId, data: dataWithoutId, version}).then(() => {
-                       return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version});
-               });
-       },
+    editDeploymentFlavor(
+        dispatch,
+        { softwareProductId, deploymentFlavorId, data, version }
+    ) {
+        let dataWithoutId = pickBy(data, (val, key) => key !== 'id');
+        return editDeploymentFlavor({
+            softwareProductId,
+            deploymentFlavorId,
+            data: dataWithoutId,
+            version
+        }).then(() => {
+            return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(
+                dispatch,
+                { softwareProductId, version }
+            );
+        });
+    },
 
-       closeDeploymentFlavorEditor(dispatch) {
-               dispatch({
-                       type: actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA
-               });
-               dispatch({
-                       type: GlobalModalActions.GLOBAL_MODAL_CLOSE
-               });
-       },
+    closeDeploymentFlavorEditor(dispatch) {
+        dispatch({
+            type:
+                actionTypes.deploymentFlavorEditor
+                    .SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA
+        });
+        dispatch({
+            type: GlobalModalActions.GLOBAL_MODAL_CLOSE
+        });
+    },
 
-       openDeploymentFlavorEditor(dispatch, {softwareProductId, modalClassName, deploymentFlavor = {}, componentsList, isEdit = false, version}) {
-               let alteredDeploymentFlavor = {...deploymentFlavor};
-               if (componentsList.length) {
-                       alteredDeploymentFlavor = {...alteredDeploymentFlavor, componentComputeAssociations: deploymentFlavor.componentComputeAssociations ?
-                               [{...deploymentFlavor.componentComputeAssociations[0], componentId: componentsList[0].id}]
-                               :
-                               [{componentId: componentsList[0].id, computeFlavorId: null}]
-                       };
-               }
-               dispatch({
-                       type: actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA,
-                       deploymentFlavor: alteredDeploymentFlavor
-               });
-               dispatch({
-                       type: GlobalModalActions.GLOBAL_MODAL_SHOW,
-                       data: {
-                               modalComponentName: modalContentMapper.DEPLOYMENT_FLAVOR_EDITOR,
-                               modalComponentProps: {softwareProductId, version},
-                               modalClassName,
-                               title: isEdit ? 'Edit Deployment Flavor' : 'Create a New Deployment Flavor'
-                       }
-               });
-       },
+    openDeploymentFlavorEditor(
+        dispatch,
+        {
+            softwareProductId,
+            modalClassName,
+            deploymentFlavor = {},
+            componentsList,
+            isEdit = false,
+            version
+        }
+    ) {
+        let alteredDeploymentFlavor = { ...deploymentFlavor };
+        if (componentsList.length) {
+            alteredDeploymentFlavor = {
+                ...alteredDeploymentFlavor,
+                componentComputeAssociations: deploymentFlavor.componentComputeAssociations
+                    ? [
+                          {
+                              ...deploymentFlavor
+                                  .componentComputeAssociations[0],
+                              componentId: componentsList[0].id
+                          }
+                      ]
+                    : [
+                          {
+                              componentId: componentsList[0].id,
+                              computeFlavorId: null
+                          }
+                      ]
+            };
+        }
+        dispatch({
+            type:
+                actionTypes.deploymentFlavorEditor
+                    .SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA,
+            deploymentFlavor: alteredDeploymentFlavor
+        });
+        dispatch({
+            type: GlobalModalActions.GLOBAL_MODAL_SHOW,
+            data: {
+                modalComponentName: modalContentMapper.DEPLOYMENT_FLAVOR_EDITOR,
+                modalComponentProps: { softwareProductId, version },
+                modalClassName,
+                title: isEdit
+                    ? 'Edit Deployment Flavor'
+                    : 'Create a New Deployment Flavor'
+            }
+        });
+    }
 };
 
-export  default SoftwareProductDeploymentActionHelper;
+export default SoftwareProductDeploymentActionHelper;
index 51469b4..6c0d3ef 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: null,
+    FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: null,
 
-       deploymentFlavorEditor: {
-               DATA_CHANGED: null,
-               SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: null,
-               SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: null
-       }
+    deploymentFlavorEditor: {
+        DATA_CHANGED: null,
+        SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: null,
+        SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: null
+    }
 });
 
 export const DEPLOYMENT_FLAVORS_FORM_NAME = 'DEPLOYMENT_FLAVORS_FORM_NAME';
index 8eb91e8..31bf09e 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductDeploymentConstants.js';
+import { actionTypes } from './SoftwareProductDeploymentConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS:
-                       return [...action.deploymentFlavors];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS:
+            return [...action.deploymentFlavors];
+        default:
+            return state;
+    }
 };
index 860d02c..e1bdd55 100644 (file)
@@ -22,74 +22,82 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
 
 export default class SoftwareProductDeployment extends React.Component {
-       state = {
-               localFilter: ''
-       };
+    state = {
+        localFilter: ''
+    };
 
-       static propTypes = {
-               onAddDeployment: PropTypes.func.isRequired,
-               onDeleteDeployment: PropTypes.func.isRequired,
-               onEditDeployment: PropTypes.func.isRequired,
-               isReadOnlyMode: PropTypes.bool.isRequired
-       };
+    static propTypes = {
+        onAddDeployment: PropTypes.func.isRequired,
+        onDeleteDeployment: PropTypes.func.isRequired,
+        onEditDeployment: PropTypes.func.isRequired,
+        isReadOnlyMode: PropTypes.bool.isRequired
+    };
 
-       render() {
-               return (
-                       <div>
-                               {this.renderList()}
-                       </div>
-               );
-       }
+    render() {
+        return <div>{this.renderList()}</div>;
+    }
 
-       renderList() {
-               let {onAddDeployment, isReadOnlyMode, componentsList} = this.props;
-               return (
-                       <ListEditorView
-                               plusButtonTitle={i18n('Add Deployment Flavor')}
-                               filterValue={this.state.localFilter}
-                               placeholder={i18n('Filter Deployment')}
-                               onAdd={() => onAddDeployment(componentsList)}
-                               isReadOnlyMode={isReadOnlyMode}
-                               title={i18n('Deployment Flavors')}
-                               onFilter={value => this.setState({localFilter: value})}
-                               twoColumns>
-                               {this.filterList().map(deploymentFlavor => this.renderListItem(deploymentFlavor, isReadOnlyMode))}
-                       </ListEditorView>
-               );
-       }
+    renderList() {
+        let { onAddDeployment, isReadOnlyMode, componentsList } = this.props;
+        return (
+            <ListEditorView
+                plusButtonTitle={i18n('Add Deployment Flavor')}
+                filterValue={this.state.localFilter}
+                placeholder={i18n('Filter Deployment')}
+                onAdd={() => onAddDeployment(componentsList)}
+                isReadOnlyMode={isReadOnlyMode}
+                title={i18n('Deployment Flavors')}
+                onFilter={value => this.setState({ localFilter: value })}
+                twoColumns>
+                {this.filterList().map(deploymentFlavor =>
+                    this.renderListItem(deploymentFlavor, isReadOnlyMode)
+                )}
+            </ListEditorView>
+        );
+    }
 
-       renderListItem(deploymentFlavor, isReadOnlyMode) {
-               let {id, model, description} = deploymentFlavor;
-               let {onEditDeployment, onDeleteDeployment, componentsList} =  this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}
-                               onSelect={() => onEditDeployment(deploymentFlavor, componentsList)}
-                               onDelete={() => onDeleteDeployment(deploymentFlavor)}>
-                               <ListEditorItemViewField>
-                                       <div className='model'>{model}</div>
-                               </ListEditorItemViewField>
-                               <ListEditorItemViewField>
-                                       <div className='description'>{description}</div>
-                               </ListEditorItemViewField>
-                       </ListEditorItemView>
-               );
-       }
+    renderListItem(deploymentFlavor, isReadOnlyMode) {
+        let { id, model, description } = deploymentFlavor;
+        let {
+            onEditDeployment,
+            onDeleteDeployment,
+            componentsList
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}
+                onSelect={() =>
+                    onEditDeployment(deploymentFlavor, componentsList)
+                }
+                onDelete={() => onDeleteDeployment(deploymentFlavor)}>
+                <ListEditorItemViewField>
+                    <div className="model">{model}</div>
+                </ListEditorItemViewField>
+                <ListEditorItemViewField>
+                    <div className="description">{description}</div>
+                </ListEditorItemViewField>
+            </ListEditorItemView>
+        );
+    }
 
-       filterList() {
-               let {deploymentFlavors} = this.props;
-               let {localFilter} = this.state;
+    filterList() {
+        let { deploymentFlavors } = this.props;
+        let { localFilter } = this.state;
 
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return deploymentFlavors.filter(({model = '', description = ''}) => {
-                               return escape(model).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return deploymentFlavors;
-               }
-       }
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return deploymentFlavors.filter(
+                ({ model = '', description = '' }) => {
+                    return (
+                        escape(model).match(filter) ||
+                        escape(description).match(filter)
+                    );
+                }
+            );
+        } else {
+            return deploymentFlavors;
+        }
+    }
 }
index c24548b..9392317 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductDeploymentEditorView from './SoftwareProductDeploymentEditorView.jsx';
 import SoftwareProdcutDeploymentActionHelper from '../SoftwareProductDeploymentActionHelper.js';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {DEPLOYMENT_FLAVORS_FORM_NAME} from '../SoftwareProductDeploymentConstants.js';
+import { DEPLOYMENT_FLAVORS_FORM_NAME } from '../SoftwareProductDeploymentConstants.js';
 
 export function mapStateToProps({
-       licenseModel,
-       softwareProduct,
-       currentScreen: {props: {isReadOnlyMode}}
+    licenseModel,
+    softwareProduct,
+    currentScreen: { props: { isReadOnlyMode } }
 }) {
-       let {
-               softwareProductEditor: {
-                       data: currentSoftwareProduct = {}
-               },
-               softwareProductComponents: {
-                       componentsList,
-                       computeFlavor: {
-                               computesList
-                       }
-               },
-               softwareProductDeployment: {
-                       deploymentFlavors,
-                       deploymentFlavorEditor: {
-                               data = {},
-                               genericFieldInfo,
-                               formReady
-                       }
-               }
-       } = softwareProduct;
+    let {
+        softwareProductEditor: { data: currentSoftwareProduct = {} },
+        softwareProductComponents: {
+            componentsList,
+            computeFlavor: { computesList }
+        },
+        softwareProductDeployment: {
+            deploymentFlavors,
+            deploymentFlavorEditor: { data = {}, genericFieldInfo, formReady }
+        }
+    } = softwareProduct;
 
-       let {
-                       featureGroup: {
-                               featureGroupsList
-                       }
-       } = licenseModel;
+    let { featureGroup: { featureGroupsList } } = licenseModel;
 
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-       let selectedFeatureGroupsIds = currentSoftwareProduct.licensingData ? currentSoftwareProduct.licensingData.featureGroups || [] : [];
-       let selectedFeatureGroupsList = featureGroupsList
-               .filter(featureGroup => selectedFeatureGroupsIds.includes(featureGroup.id))
-               .map(featureGroup => ({value: featureGroup.id, label: featureGroup.name}));
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    let selectedFeatureGroupsIds = currentSoftwareProduct.licensingData
+        ? currentSoftwareProduct.licensingData.featureGroups || []
+        : [];
+    let selectedFeatureGroupsList = featureGroupsList
+        .filter(featureGroup =>
+            selectedFeatureGroupsIds.includes(featureGroup.id)
+        )
+        .map(featureGroup => ({
+            value: featureGroup.id,
+            label: featureGroup.name
+        }));
 
-       let DFNames = {};
+    let DFNames = {};
 
-       deploymentFlavors.map(deployment => {
-               DFNames[deployment.model.toLowerCase()] = deployment.id;
-       });
+    deploymentFlavors.map(deployment => {
+        DFNames[deployment.model.toLowerCase()] = deployment.id;
+    });
 
-       return {
-               data,
-               selectedFeatureGroupsList,
-               genericFieldInfo,
-               DFNames,
-               isFormValid,
-               formReady,
-               isReadOnlyMode,
-               componentsList,
-               computesList,
-               isEdit: Boolean(data.id)
-       };
+    return {
+        data,
+        selectedFeatureGroupsList,
+        genericFieldInfo,
+        DFNames,
+        isFormValid,
+        formReady,
+        isReadOnlyMode,
+        componentsList,
+        computesList,
+        isEdit: Boolean(data.id)
+    };
 }
 
-function mapActionsToProps(dispatch, {softwareProductId, version}) {
-       return {
-               onDataChanged: (deltaData, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: DEPLOYMENT_FLAVORS_FORM_NAME, customValidations}),
-               onClose: () => SoftwareProdcutDeploymentActionHelper.closeDeploymentFlavorEditor(dispatch),
-               onCreate: data =>  SoftwareProdcutDeploymentActionHelper.createDeploymentFlavor(dispatch, {softwareProductId, data, version}),
-               onEdit: data =>  SoftwareProdcutDeploymentActionHelper.editDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId: data.id, data, version}),
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, DEPLOYMENT_FLAVORS_FORM_NAME)
-       };
+function mapActionsToProps(dispatch, { softwareProductId, version }) {
+    return {
+        onDataChanged: (deltaData, customValidations) =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: DEPLOYMENT_FLAVORS_FORM_NAME,
+                customValidations
+            }),
+        onClose: () =>
+            SoftwareProdcutDeploymentActionHelper.closeDeploymentFlavorEditor(
+                dispatch
+            ),
+        onCreate: data =>
+            SoftwareProdcutDeploymentActionHelper.createDeploymentFlavor(
+                dispatch,
+                {
+                    softwareProductId,
+                    data,
+                    version
+                }
+            ),
+        onEdit: data =>
+            SoftwareProdcutDeploymentActionHelper.editDeploymentFlavor(
+                dispatch,
+                {
+                    softwareProductId,
+                    deploymentFlavorId: data.id,
+                    data,
+                    version
+                }
+            ),
+        onValidateForm: () =>
+            ValidationHelper.validateForm(
+                dispatch,
+                DEPLOYMENT_FLAVORS_FORM_NAME
+            )
+    };
 }
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductDeploymentEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductDeploymentEditorView
+);
index 70836e8..16e73d2 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, DEPLOYMENT_FLAVORS_FORM_NAME} from '../SoftwareProductDeploymentConstants.js';;
+import {
+    actionTypes,
+    DEPLOYMENT_FLAVORS_FORM_NAME
+} from '../SoftwareProductDeploymentConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA:
-                       return {
-                               ...state,
-                               data: action.deploymentFlavor,
-                               formReady: null,
-                               formName: DEPLOYMENT_FLAVORS_FORM_NAME,
-                               genericFieldInfo: {
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 500}]
-                                       },
-                                       'model' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       }
-                               }
-                       };
-               case actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA:
-                       return {};
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.deploymentFlavorEditor
+            .SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA:
+            return {
+                ...state,
+                data: action.deploymentFlavor,
+                formReady: null,
+                formName: DEPLOYMENT_FLAVORS_FORM_NAME,
+                genericFieldInfo: {
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 500 }]
+                    },
+                    model: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    }
+                }
+            };
+        case actionTypes.deploymentFlavorEditor
+            .SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA:
+            return {};
+        default:
+            return state;
+    }
 };
index 7c9ae43..e44d2bd 100644 (file)
@@ -11,127 +11,240 @@ import SelectActionTableCell from 'nfvo-components/table/SelectActionTableCell.j
 import Validator from 'nfvo-utils/Validator.js';
 
 export default class SoftwareProductDeploymentEditorView extends React.Component {
-       render() {
-               let {data, isEdit, onClose, onDataChanged, isReadOnlyMode, selectedFeatureGroupsList, componentsList, computesList, genericFieldInfo} = this.props;
-               let {model, description, featureGroupId, componentComputeAssociations = []} = data;
-               let featureGroupsExist = selectedFeatureGroupsList.length > 0;
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       ref='validationForm'
-                                       hasButtons={true}
-                                       labledButtons={true}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       onSubmit={ () => this.submit() }
-                                       submitButtonText={isEdit ? i18n('Save') : i18n('Create')}
-                                       onReset={ () => onClose() }
-                                       onValidateForm={() => this.validate() }
-                                       isValid={this.props.isFormValid}
-                                       formReady={this.props.formReady}
-                                       className='vsp-deployment-editor'>
-                                       <GridSection hasLastColSet>
-                                               <GridItem colSpan={1}>
-                                                       <Input
-                                                               onChange={model => onDataChanged({model}, {model: model => this.validateName(model)})}
-                                                               label={i18n('Model')}
-                                                               value={model}
-                                                               data-test-id='deployment-model'
-                                                               isValid={genericFieldInfo.model.isValid}
-                                                               errorText={genericFieldInfo.model.errorText}
-                                                               isRequired={true}
-                                                               type='text'/>
-                                               </GridItem>
-                                               <GridItem colSpan={3} lastColInRow>
-                                                       <Input
-                                                               onChange={description => onDataChanged({description})}
-                                                               label={i18n('Description')}
-                                                               value={description}
-                                                               data-test-id='deployment-description'
-                                                               isValid={genericFieldInfo.description.isValid}
-                                                               errorText={genericFieldInfo.description.errorText}
-                                                               type='text'/>
-                                               </GridItem>
-                                       </GridSection>
-                                       <GridSection className={`deployment-feature-groups-section${!featureGroupsExist ? ' no-feature-groups' : ''}`} title={i18n('License Details')} hasLastColSet>
-                                               <GridItem colSpan={1}>
-                                                       <SelectInput
-                                                               data-test-id='deployment-feature-groups'
-                                                               label={i18n('Feature Group')}
-                                                               value={featureGroupId}
-                                                               onChange={featureGroup => onDataChanged({featureGroupId: featureGroup ? featureGroup.value : null})}
-                                                               type='select'
-                                                               clearable={true}
-                                                               disabled={isReadOnlyMode || !featureGroupsExist}
-                                                               className='field-section'
-                                                               options={selectedFeatureGroupsList}/>
-                                               </GridItem>
-                                       </GridSection>
-                                       {!featureGroupsExist && <GridSection className='deployment-feature-group-warning-section'>
-                                               <GridItem colSpan={3}>
-                                                       <span>{i18n('Please assign Feature Groups in VSP General')}</span>
-                                               </GridItem>
-                                       </GridSection>}
-                                       <GridSection title={i18n('Assign VFCs and Compute Flavors')} className='vfc-table' hasLastColSet>
-                                               <GridItem colSpan={4} lastColInRow>
-                                                       <SelectActionTable
-                                                               columns={['Virtual Function Components', 'Compute Flavors']}
-                                                               numOfIcons={0}>
-                                                               {componentComputeAssociations.map( (association, index) =>
-                                                                       <SelectActionTableRow key={association.componentId}>
-                                                                               <SelectActionTableCell
-                                                                                       options={
-                                                                                               componentsList
-                                                                                               .map(component => ({value: component.id, label: component.displayName}) )
-                                                                                       }
-                                                                                       selected={association.componentId}
-                                                                                       onChange={componentId => {
-                                                                                               let newAssociations = [...componentComputeAssociations];
-                                                                                               newAssociations[index] = {...newAssociations[index], componentId};
-                                                                                               onDataChanged({componentComputeAssociations: newAssociations});
-                                                                                       }}
-                                                                                       disabled={true}/>
-                                                                               <SelectActionTableCell
-                                                                                       options={
-                                                                                               computesList
-                                                                                               .filter(compute => compute.componentId === association.componentId)
-                                                                                               .map(compute => ({value: compute.computeFlavorId, label: compute.name}) )
-                                                                                       }
-                                                                                       selected={association.computeFlavorId}
-                                                                                       onChange={computeFlavorId => {
-                                                                                               let newAssociations = [...componentComputeAssociations];
-                                                                                               newAssociations[index] = {...newAssociations[index], computeFlavorId};
-                                                                                               onDataChanged({componentComputeAssociations: newAssociations});
-                                                                                       }}
-                                                                                       disabled={isReadOnlyMode}/>
-                                                                       </SelectActionTableRow>
-                                                               )}
-                                                       </SelectActionTable>
-                                               </GridItem>
-                                       </GridSection>
-                               </Form>}
-                       </div>
-               );
-       }
+    render() {
+        let {
+            data,
+            isEdit,
+            onClose,
+            onDataChanged,
+            isReadOnlyMode,
+            selectedFeatureGroupsList,
+            componentsList,
+            computesList,
+            genericFieldInfo
+        } = this.props;
+        let {
+            model,
+            description,
+            featureGroupId,
+            componentComputeAssociations = []
+        } = data;
+        let featureGroupsExist = selectedFeatureGroupsList.length > 0;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        onSubmit={() => this.submit()}
+                        submitButtonText={
+                            isEdit ? i18n('Save') : i18n('Create')
+                        }
+                        onReset={() => onClose()}
+                        onValidateForm={() => this.validate()}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        className="vsp-deployment-editor">
+                        <GridSection hasLastColSet>
+                            <GridItem colSpan={1}>
+                                <Input
+                                    onChange={model =>
+                                        onDataChanged(
+                                            { model },
+                                            {
+                                                model: model =>
+                                                    this.validateName(model)
+                                            }
+                                        )
+                                    }
+                                    label={i18n('Model')}
+                                    value={model}
+                                    data-test-id="deployment-model"
+                                    isValid={genericFieldInfo.model.isValid}
+                                    errorText={genericFieldInfo.model.errorText}
+                                    isRequired={true}
+                                    type="text"
+                                />
+                            </GridItem>
+                            <GridItem colSpan={3} lastColInRow>
+                                <Input
+                                    onChange={description =>
+                                        onDataChanged({ description })
+                                    }
+                                    label={i18n('Description')}
+                                    value={description}
+                                    data-test-id="deployment-description"
+                                    isValid={
+                                        genericFieldInfo.description.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.description.errorText
+                                    }
+                                    type="text"
+                                />
+                            </GridItem>
+                        </GridSection>
+                        <GridSection
+                            className={`deployment-feature-groups-section${
+                                !featureGroupsExist ? ' no-feature-groups' : ''
+                            }`}
+                            title={i18n('License Details')}
+                            hasLastColSet>
+                            <GridItem colSpan={1}>
+                                <SelectInput
+                                    data-test-id="deployment-feature-groups"
+                                    label={i18n('Feature Group')}
+                                    value={featureGroupId}
+                                    onChange={featureGroup =>
+                                        onDataChanged({
+                                            featureGroupId: featureGroup
+                                                ? featureGroup.value
+                                                : null
+                                        })
+                                    }
+                                    type="select"
+                                    clearable={true}
+                                    disabled={
+                                        isReadOnlyMode || !featureGroupsExist
+                                    }
+                                    className="field-section"
+                                    options={selectedFeatureGroupsList}
+                                />
+                            </GridItem>
+                        </GridSection>
+                        {!featureGroupsExist && (
+                            <GridSection className="deployment-feature-group-warning-section">
+                                <GridItem colSpan={3}>
+                                    <span>
+                                        {i18n(
+                                            'Please assign Feature Groups in VSP General'
+                                        )}
+                                    </span>
+                                </GridItem>
+                            </GridSection>
+                        )}
+                        <GridSection
+                            title={i18n('Assign VFCs and Compute Flavors')}
+                            className="vfc-table"
+                            hasLastColSet>
+                            <GridItem colSpan={4} lastColInRow>
+                                <SelectActionTable
+                                    columns={[
+                                        'Virtual Function Components',
+                                        'Compute Flavors'
+                                    ]}
+                                    numOfIcons={0}>
+                                    {componentComputeAssociations.map(
+                                        (association, index) => (
+                                            <SelectActionTableRow
+                                                key={association.componentId}>
+                                                <SelectActionTableCell
+                                                    options={componentsList.map(
+                                                        component => ({
+                                                            value: component.id,
+                                                            label:
+                                                                component.displayName
+                                                        })
+                                                    )}
+                                                    selected={
+                                                        association.componentId
+                                                    }
+                                                    onChange={componentId => {
+                                                        let newAssociations = [
+                                                            ...componentComputeAssociations
+                                                        ];
+                                                        newAssociations[
+                                                            index
+                                                        ] = {
+                                                            ...newAssociations[
+                                                                index
+                                                            ],
+                                                            componentId
+                                                        };
+                                                        onDataChanged({
+                                                            componentComputeAssociations: newAssociations
+                                                        });
+                                                    }}
+                                                    disabled={true}
+                                                />
+                                                <SelectActionTableCell
+                                                    options={computesList
+                                                        .filter(
+                                                            compute =>
+                                                                compute.componentId ===
+                                                                association.componentId
+                                                        )
+                                                        .map(compute => ({
+                                                            value:
+                                                                compute.computeFlavorId,
+                                                            label: compute.name
+                                                        }))}
+                                                    selected={
+                                                        association.computeFlavorId
+                                                    }
+                                                    onChange={computeFlavorId => {
+                                                        let newAssociations = [
+                                                            ...componentComputeAssociations
+                                                        ];
+                                                        newAssociations[
+                                                            index
+                                                        ] = {
+                                                            ...newAssociations[
+                                                                index
+                                                            ],
+                                                            computeFlavorId
+                                                        };
+                                                        onDataChanged({
+                                                            componentComputeAssociations: newAssociations
+                                                        });
+                                                    }}
+                                                    disabled={isReadOnlyMode}
+                                                />
+                                            </SelectActionTableRow>
+                                        )
+                                    )}
+                                </SelectActionTable>
+                            </GridItem>
+                        </GridSection>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-       validateName(value) {
-               const {data: {id = ''}, DFNames} = this.props;
-               const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: DFNames});
+    validateName(value) {
+        const { data: { id = '' }, DFNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: DFNames
+        });
 
-               return !isExists ?  {isValid: true, errorText: ''} :
-                       {isValid: false, errorText: i18n('Deployment flavor by the name \'' + value + '\' already exists. Deployment flavor name must be unique')};
-       }
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "Deployment flavor by the name '" +
+                          value +
+                          "' already exists. Deployment flavor name must be unique"
+                  )
+              };
+    }
 
-       submit(){
-               let {isEdit, onCreate, onEdit, onClose, data} = this.props;
-               if (isEdit) {
-                       onEdit(data);
-               } else {
-                       onCreate(data);
-               }
-               onClose();
-       }
+    submit() {
+        let { isEdit, onCreate, onEdit, onClose, data } = this.props;
+        if (isEdit) {
+            onEdit(data);
+        } else {
+            onCreate(data);
+        }
+        onClose();
+    }
 
-       validate() {
-               this.props.onValidateForm();
-       }
+    validate() {
+        this.props.onValidateForm();
+    }
 }
index 0973537..8a3279a 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 import SoftwareProductDetailsView from './SoftwareProductDetailsView.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import {PRODUCT_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-import {actionTypes as modalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { PRODUCT_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {
+    actionTypes as modalActionTypes,
+    modalSizes
+} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
 export const mapStateToProps = ({
-       finalizedLicenseModelList,
-       archivedLicenseModelList,
-       softwareProduct,
-       licenseModel: {licenseAgreement, featureGroup}
+    finalizedLicenseModelList,
+    archivedLicenseModelList,
+    softwareProduct,
+    licenseModel: { licenseAgreement, featureGroup }
 }) => {
+    let {
+        softwareProductEditor: {
+            data: currentSoftwareProduct,
+            licensingVersionsList = [],
+            genericFieldInfo
+        },
+        softwareProductCategories,
+        softwareProductQuestionnaire
+    } = softwareProduct;
+    let { licensingData = {}, licensingVersion } = currentSoftwareProduct;
+    let licenseAgreementList = [],
+        filteredFeatureGroupsList = [];
+    licenseAgreementList = licensingVersion
+        ? licenseAgreement.licenseAgreementList
+        : [];
+    if (licensingVersion && licensingData && licensingData.licenseAgreement) {
+        let selectedLicenseAgreement = licenseAgreementList.find(
+            la => la.id === licensingData.licenseAgreement
+        );
+        if (selectedLicenseAgreement) {
+            let featureGroupsList = featureGroup.featureGroupsList.filter(
+                ({ referencingLicenseAgreements }) =>
+                    referencingLicenseAgreements.includes(
+                        selectedLicenseAgreement.id
+                    )
+            );
+            if (featureGroupsList.length) {
+                filteredFeatureGroupsList = featureGroupsList.map(
+                    featureGroup => ({
+                        enum: featureGroup.id,
+                        title: featureGroup.name
+                    })
+                );
+            }
+        }
+    }
+    let {
+        qdata,
+        qgenericFieldInfo: qGenericFieldInfo,
+        dataMap
+    } = softwareProductQuestionnaire;
 
-       let {softwareProductEditor: {data: currentSoftwareProduct, licensingVersionsList = [], genericFieldInfo}, softwareProductCategories, softwareProductQuestionnaire} = softwareProduct;
-       let {licensingData = {}, licensingVersion} = currentSoftwareProduct;
-       let licenseAgreementList = [], filteredFeatureGroupsList = [];
-       licenseAgreementList = licensingVersion ?
-               licenseAgreement.licenseAgreementList : [];
-       if(licensingVersion && licensingData && licensingData.licenseAgreement) {
-               let selectedLicenseAgreement = licenseAgreementList.find(la => la.id === licensingData.licenseAgreement);
-               if (selectedLicenseAgreement) {
-                       let featureGroupsList = featureGroup.featureGroupsList.filter(({referencingLicenseAgreements}) => referencingLicenseAgreements.includes(selectedLicenseAgreement.id));
-                       if (featureGroupsList.length) {
-                               filteredFeatureGroupsList = featureGroupsList.map(featureGroup => ({enum: featureGroup.id, title: featureGroup.name}));
-                       }
-               }
-       }
-       let {qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap} = softwareProductQuestionnaire;
-
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-       const isVendorArchived = archivedLicenseModelList.find(item => item.id === currentSoftwareProduct.vendorId);
-       return {
-               currentSoftwareProduct,
-               softwareProductCategories,
-               licenseAgreementList,
-               licensingVersionsList,
-               featureGroupsList: filteredFeatureGroupsList,
-               finalizedLicenseModelList,
-               qdata,
-               isFormValid,
-               genericFieldInfo,
-               qGenericFieldInfo,
-               dataMap,
-               isVendorArchived: !!isVendorArchived
-       };
-
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    const isVendorArchived = archivedLicenseModelList.find(
+        item => item.id === currentSoftwareProduct.vendorId
+    );
+    return {
+        currentSoftwareProduct,
+        softwareProductCategories,
+        licenseAgreementList,
+        licensingVersionsList,
+        featureGroupsList: filteredFeatureGroupsList,
+        finalizedLicenseModelList,
+        qdata,
+        isFormValid,
+        genericFieldInfo,
+        qGenericFieldInfo,
+        dataMap,
+        isVendorArchived: !!isVendorArchived
+    };
 };
 
-export const mapActionsToProps = (dispatch, {version}) => {
-       return {
-               onDataChanged: (deltaData, formName) => ValidationHelper.dataChanged(dispatch, {deltaData, formName}),
-               onVendorParamChanged: (deltaData, formName) => SoftwareProductActionHelper.softwareProductEditorVendorChanged(dispatch, {deltaData, formName}),
-               onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: PRODUCT_QUESTIONNAIRE}),
-               onValidityChanged: isValidityData => SoftwareProductActionHelper.setIsValidityData(dispatch, {isValidityData}),
-               onSubmit: (softwareProduct, qdata) => SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata, version}),
-               onArchivedVendorRemove: ({onVendorParamChanged, finalizedLicenseModelList, vendorName}) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_SHOW,
-                       data:{
-                               title: i18n('Change Archived VLM'),
-                               modalComponentName: modalContentMapper.VENDOR_SELECTOR,
-                               modalComponentProps: {
-                                       size: modalSizes.MEDIUM,
-                                       finalizedLicenseModelList,
-                                       vendorName,
-                                       onClose: () => dispatch({type: modalActionTypes.GLOBAL_MODAL_CLOSE}),
-                                       onConfirm: (vendorId) => onVendorParamChanged({vendorId}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)
-                               }
-                       }
-               })
-       };
+export const mapActionsToProps = (dispatch, { version }) => {
+    return {
+        onDataChanged: (deltaData, formName) =>
+            ValidationHelper.dataChanged(dispatch, { deltaData, formName }),
+        onVendorParamChanged: (deltaData, formName) =>
+            SoftwareProductActionHelper.softwareProductEditorVendorChanged(
+                dispatch,
+                { deltaData, formName }
+            ),
+        onQDataChanged: deltaData =>
+            ValidationHelper.qDataChanged(dispatch, {
+                deltaData,
+                qName: PRODUCT_QUESTIONNAIRE
+            }),
+        onValidityChanged: isValidityData =>
+            SoftwareProductActionHelper.setIsValidityData(dispatch, {
+                isValidityData
+            }),
+        onSubmit: (softwareProduct, qdata) =>
+            SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
+                softwareProduct,
+                qdata,
+                version
+            }),
+        onArchivedVendorRemove: ({
+            onVendorParamChanged,
+            finalizedLicenseModelList,
+            vendorName
+        }) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_SHOW,
+                data: {
+                    title: i18n('Change Archived VLM'),
+                    modalComponentName: modalContentMapper.VENDOR_SELECTOR,
+                    modalComponentProps: {
+                        size: modalSizes.MEDIUM,
+                        finalizedLicenseModelList,
+                        vendorName,
+                        onClose: () =>
+                            dispatch({
+                                type: modalActionTypes.GLOBAL_MODAL_CLOSE
+                            }),
+                        onConfirm: vendorId =>
+                            onVendorParamChanged(
+                                { vendorId },
+                                forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+                            )
+                    }
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDetailsView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductDetailsView);
index 1a29326..1e4a0df 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {
+    actionTypes,
+    forms
+} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED:
-                       return {
-                               ...state,
-                               isValidityData: action.isValidityData
-                       };
-               case actionTypes.SOFTWARE_PRODUCT_LOADED:
-                       return {
-                               ...state,
-                               formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS,
-                               genericFieldInfo: {
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'validateName', data: true}, {type: 'maxLength', data: 25}, {type: 'required', data: true}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}]
-                                       }
-                               },
-                               data: action.response
-                       };
-               case actionTypes.TOGGLE_NAVIGATION_ITEM:
-                       return {
-                               ...state,
-                               mapOfExpandedIds: action.mapOfExpandedIds
-                       };
-               case actionTypes.LOAD_LICENSING_VERSIONS_LIST:
-                       return {
-                               ...state,
-                               licensingVersionsList: action.licensingVersionsList
-                       };
-               case actionTypes.CANDIDATE_IN_PROCESS: 
-                       return {
-                               ...state,
-                               data: {...state.data, candidateOnboardingOrigin: true}                          
-                       };      
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED:
+            return {
+                ...state,
+                isValidityData: action.isValidityData
+            };
+        case actionTypes.SOFTWARE_PRODUCT_LOADED:
+            return {
+                ...state,
+                formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS,
+                genericFieldInfo: {
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'validateName', data: true },
+                            { type: 'maxLength', data: 25 },
+                            { type: 'required', data: true }
+                        ]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'required', data: true }]
+                    }
+                },
+                data: action.response
+            };
+        case actionTypes.TOGGLE_NAVIGATION_ITEM:
+            return {
+                ...state,
+                mapOfExpandedIds: action.mapOfExpandedIds
+            };
+        case actionTypes.LOAD_LICENSING_VERSIONS_LIST:
+            return {
+                ...state,
+                licensingVersionsList: action.licensingVersionsList
+            };
+        case actionTypes.CANDIDATE_IN_PROCESS:
+            return {
+                ...state,
+                data: { ...state.data, candidateOnboardingOrigin: true }
+            };
+        default:
+            return state;
+    }
 };
index c2a3e0b..9c20723 100644 (file)
@@ -22,57 +22,77 @@ import Input from 'nfvo-components/input/validation/Input.jsx';
 import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
 
 class VendorSelector extends React.Component {
-       static propTypes = {
-               finalizedLicenseModelList: PropTypes.array,
-               vendorName: PropTypes.string,
-               onClose: PropTypes.func.isRequired,
-               onConfirm: PropTypes.func.isRequired
-       }
-       constructor(props){
-               super(props);
-               const selectedValue = props.finalizedLicenseModelList.length ? props.finalizedLicenseModelList[0].id : '';
-               this.state = {
-                       selectedValue
-               };
-       }
-       submit() {
-               const vendor = this.props.finalizedLicenseModelList.find(item => item.id === this.state.selectedValue);
-               this.props.onConfirm(vendor.id);
-               this.props.onClose();
-       }
-       render() {
-               const {finalizedLicenseModelList, vendorName, onClose} =  this.props;
-               const {selectedValue} = this.state;             
-               return (
-                       <div className='vsp-details-vendor-select'>
-                               <Form 
-                                       onSubmit={() => this.submit()}
-                                       onReset={() => onClose()}
-                                       isValid = {!!selectedValue}
-                                       submitButtonText={i18n('Save')}
-                                       hasButtons={true}>
-                                               <div className='vendor-selector-modal-title'>{`${i18n('The VLM')} '${vendorName}' ${i18n('assigned to this VSP is archived')}.`}</div>
-                                               <div className='vendor-selector-modal-additional-text'>{i18n('If you select a different VLM you will not be able to reselect the archived VLM.')}</div>
-                                               <Input
-                                                       data-test-id='vsp-vendor-name-select'
-                                                       label={i18n('Vendor')}
-                                                       type='select'
-                                                       onChange={e => {this.setState({
-                                                               selectedValue: e.target.options[e.target.selectedIndex].value
-                                                       });}} 
-                                                       value={selectedValue}>
-                                                       <option key='emtyVendor' value=''>{i18n('please select...')}</option>
-                                                       {sortByStringProperty(
-                                                               finalizedLicenseModelList,
-                                                               'name'
-                                                       ).map(lm => <option key={lm.id} value={lm.id}>{lm.name}</option>)
-                                                       }
-                                               </Input>
-                               </Form>
-                       </div>
-               );
-       }
+    static propTypes = {
+        finalizedLicenseModelList: PropTypes.array,
+        vendorName: PropTypes.string,
+        onClose: PropTypes.func.isRequired,
+        onConfirm: PropTypes.func.isRequired
+    };
+    constructor(props) {
+        super(props);
+        const selectedValue = props.finalizedLicenseModelList.length
+            ? props.finalizedLicenseModelList[0].id
+            : '';
+        this.state = {
+            selectedValue
+        };
+    }
+    submit() {
+        const vendor = this.props.finalizedLicenseModelList.find(
+            item => item.id === this.state.selectedValue
+        );
+        this.props.onConfirm(vendor.id);
+        this.props.onClose();
+    }
+    render() {
+        const { finalizedLicenseModelList, vendorName, onClose } = this.props;
+        const { selectedValue } = this.state;
+        return (
+            <div className="vsp-details-vendor-select">
+                <Form
+                    onSubmit={() => this.submit()}
+                    onReset={() => onClose()}
+                    isValid={!!selectedValue}
+                    submitButtonText={i18n('Save')}
+                    hasButtons={true}>
+                    <div className="vendor-selector-modal-title">{`${i18n(
+                        'The VLM'
+                    )} '${vendorName}' ${i18n(
+                        'assigned to this VSP is archived'
+                    )}.`}</div>
+                    <div className="vendor-selector-modal-additional-text">
+                        {i18n(
+                            'If you select a different VLM you will not be able to reselect the archived VLM.'
+                        )}
+                    </div>
+                    <Input
+                        data-test-id="vsp-vendor-name-select"
+                        label={i18n('Vendor')}
+                        type="select"
+                        onChange={e => {
+                            this.setState({
+                                selectedValue:
+                                    e.target.options[e.target.selectedIndex]
+                                        .value
+                            });
+                        }}
+                        value={selectedValue}>
+                        <option key="emtyVendor" value="">
+                            {i18n('please select...')}
+                        </option>
+                        {sortByStringProperty(
+                            finalizedLicenseModelList,
+                            'name'
+                        ).map(lm => (
+                            <option key={lm.id} value={lm.id}>
+                                {lm.name}
+                            </option>
+                        ))}
+                    </Input>
+                </Form>
+            </div>
+        );
+    }
 }
 
 export default VendorSelector;
-
index 24aa319..12b1ead 100644 (file)
@@ -13,7 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import React, {Component} from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 
 import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -24,427 +24,642 @@ import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
-import {forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import { forms } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
 
-const DeprecatedVlmInfo = ({vendorName, onVendorRemove}) => {
-       return (
-               <div className='depricated-vlm-info'>
-                       <Input
-                               data-test-id='vsp-vendor-name'
-                               isRequired={true}
-                               onClick={() => onVendorRemove()}
-                               label={i18n('Vendor')}
-                               type='select'
-                               value={`${vendorName} (Archived)`}>
-                               <option key={vendorName} value={`${vendorName} (Archived)`}>{`${vendorName} (Archived)`}</option>
-                       </Input>
-               </div>
-       );
+const DeprecatedVlmInfo = ({ vendorName, onVendorRemove }) => {
+    return (
+        <div className="depricated-vlm-info">
+            <Input
+                data-test-id="vsp-vendor-name"
+                isRequired={true}
+                onClick={() => onVendorRemove()}
+                label={i18n('Vendor')}
+                type="select"
+                value={`${vendorName} (Archived)`}>
+                <option
+                    key={vendorName}
+                    value={`${vendorName} (Archived)`}>{`${vendorName} (Archived)`}</option>
+            </Input>
+        </div>
+    );
 };
 
 class GeneralSection extends React.Component {
-       static propTypes = {
-               vendorId: PropTypes.string,
-               name: PropTypes.string,
-               description: PropTypes.string,
-               subCategory: PropTypes.string,
-               softwareProductCategories: PropTypes.array,
-               finalizedLicenseModelList: PropTypes.array,
-               onDataChanged: PropTypes.func.isRequired,
-               onVendorParamChanged: PropTypes.func.isRequired,
-               onSelectSubCategory: PropTypes.func.isRequired,
-               isVendorArchived: PropTypes.bool,
-               onArchivedVendorRemove: PropTypes.func
-       };
+    static propTypes = {
+        vendorId: PropTypes.string,
+        name: PropTypes.string,
+        description: PropTypes.string,
+        subCategory: PropTypes.string,
+        softwareProductCategories: PropTypes.array,
+        finalizedLicenseModelList: PropTypes.array,
+        onDataChanged: PropTypes.func.isRequired,
+        onVendorParamChanged: PropTypes.func.isRequired,
+        onSelectSubCategory: PropTypes.func.isRequired,
+        isVendorArchived: PropTypes.bool,
+        onArchivedVendorRemove: PropTypes.func
+    };
 
-       onVendorParamChanged(e) {
-               const selectedIndex = e.target.selectedIndex;
-               const vendorId = e.target.options[selectedIndex].value;
-               this.props.onVendorParamChanged({vendorId}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
+    onVendorParamChanged(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const vendorId = e.target.options[selectedIndex].value;
+        this.props.onVendorParamChanged(
+            { vendorId },
+            forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+        );
+    }
 
-       }
+    onSelectSubCategory(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const subCategory = e.target.options[selectedIndex].value;
+        this.props.onSelectSubCategory(subCategory);
+    }
+    onVendorRemove() {
+        const {
+            finalizedLicenseModelList,
+            vendorName,
+            onVendorParamChanged
+        } = this.props;
+        this.props.onArchivedVendorRemove({
+            finalizedLicenseModelList,
+            onVendorParamChanged,
+            vendorName
+        });
+    }
 
-       onSelectSubCategory(e) {
-               const selectedIndex = e.target.selectedIndex;
-               const subCategory = e.target.options[selectedIndex].value;
-               this.props.onSelectSubCategory(subCategory);
-       }
-       onVendorRemove() {
-               const {finalizedLicenseModelList, vendorName, onVendorParamChanged} = this.props;
-               this.props.onArchivedVendorRemove({finalizedLicenseModelList, onVendorParamChanged, vendorName});
-       }
-
-       render (){
-               let {genericFieldInfo} = this.props;
-               return (
-                       <div>
-                       {genericFieldInfo && <GridSection title={i18n('General')} className='grid-section-general'>
-                       <GridItem>
-                               <Input
-                                       data-test-id='vsp-name'
-                                       label={i18n('Name')}
-                                       type='text'
-                                       value={this.props.name}
-                                       isRequired={true}
-                                       errorText={genericFieldInfo.name.errorText}
-                                       isValid={genericFieldInfo.name.isValid}
-                                       onChange={name => name.length <= 25 && this.props.onDataChanged({name}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/>
-                               {this.props.isVendorArchived ? 
-                                       <DeprecatedVlmInfo  onVendorRemove={()=>this.onVendorRemove()} vendorName={this.props.vendorName} /> :  
-                                       <Input
-                                               data-test-id='vsp-vendor-name'
-                                               label={i18n('Vendor')}
-                                               type='select'
-                                               value={this.props.vendorId}
-                                               onChange={e => this.onVendorParamChanged(e)}>
-                                               {sortByStringProperty(
-                                                       this.props.finalizedLicenseModelList,
-                                                       'name'
-                                               ).map(lm => <option key={lm.id} value={lm.id}>{lm.name}</option>)
-                                               }
-                                       </Input>
-                               }
-                               <Input
-                                       data-test-id='vsp-category-name'
-                                       label={i18n('Category')}
-                                       type='select'
-                                       value={this.props.subCategory}
-                                       onChange={e => this.onSelectSubCategory(e)}>
-                                       {
-                                               this.props.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>
-                       </GridItem>
-                       <GridItem colSpan={2} stretch>
-                               <Input
-                                       data-test-id='vsp-description'
-                                       label={i18n('Description')}
-                                       type='textarea'
-                                       isRequired={true}
-                                       isValid={genericFieldInfo.description.isValid}
-                                       errorText={genericFieldInfo.description.errorText}
-                                       value={this.props.description}
-                                       onChange={description => this.props.onDataChanged({description}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/>
-                       </GridItem>
-               </GridSection>}
-               </div>);
-       }
+    render() {
+        let { genericFieldInfo } = this.props;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <GridSection
+                        title={i18n('General')}
+                        className="grid-section-general">
+                        <GridItem>
+                            <Input
+                                data-test-id="vsp-name"
+                                label={i18n('Name')}
+                                type="text"
+                                value={this.props.name}
+                                isRequired={true}
+                                errorText={genericFieldInfo.name.errorText}
+                                isValid={genericFieldInfo.name.isValid}
+                                onChange={name =>
+                                    name.length <= 25 &&
+                                    this.props.onDataChanged(
+                                        { name },
+                                        forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+                                    )
+                                }
+                            />
+                            {this.props.isVendorArchived ? (
+                                <DeprecatedVlmInfo
+                                    onVendorRemove={() => this.onVendorRemove()}
+                                    vendorName={this.props.vendorName}
+                                />
+                            ) : (
+                                <Input
+                                    data-test-id="vsp-vendor-name"
+                                    label={i18n('Vendor')}
+                                    type="select"
+                                    value={this.props.vendorId}
+                                    onChange={e =>
+                                        this.onVendorParamChanged(e)
+                                    }>
+                                    {sortByStringProperty(
+                                        this.props.finalizedLicenseModelList,
+                                        'name'
+                                    ).map(lm => (
+                                        <option key={lm.id} value={lm.id}>
+                                            {lm.name}
+                                        </option>
+                                    ))}
+                                </Input>
+                            )}
+                            <Input
+                                data-test-id="vsp-category-name"
+                                label={i18n('Category')}
+                                type="select"
+                                value={this.props.subCategory}
+                                onChange={e => this.onSelectSubCategory(e)}>
+                                {this.props.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>
+                        </GridItem>
+                        <GridItem colSpan={2} stretch>
+                            <Input
+                                data-test-id="vsp-description"
+                                label={i18n('Description')}
+                                type="textarea"
+                                isRequired={true}
+                                isValid={genericFieldInfo.description.isValid}
+                                errorText={
+                                    genericFieldInfo.description.errorText
+                                }
+                                value={this.props.description}
+                                onChange={description =>
+                                    this.props.onDataChanged(
+                                        { description },
+                                        forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+                                    )
+                                }
+                            />
+                        </GridItem>
+                    </GridSection>
+                )}
+            </div>
+        );
+    }
 }
 class LicensesSection extends React.Component {
-       static propTypes = {
-               onVendorParamChanged: PropTypes.func.isRequired,
-               vendorId: PropTypes.string,
-               licensingVersion: PropTypes.string,
-               licensingVersionsList: PropTypes.array,
-               licensingData: PropTypes.shape({
-                       licenceAgreement: PropTypes.string,
-                       featureGroups: PropTypes.array
-               }),
-               onFeatureGroupsChanged: PropTypes.func.isRequired,
-               onLicensingDataChanged: PropTypes.func.isRequired,
-               featureGroupsList: PropTypes.array,
-               licenseAgreementList: PropTypes.array, 
-               isVendorArchived: PropTypes.bool
-       };
+    static propTypes = {
+        onVendorParamChanged: PropTypes.func.isRequired,
+        vendorId: PropTypes.string,
+        licensingVersion: PropTypes.string,
+        licensingVersionsList: PropTypes.array,
+        licensingData: PropTypes.shape({
+            licenceAgreement: PropTypes.string,
+            featureGroups: PropTypes.array
+        }),
+        onFeatureGroupsChanged: PropTypes.func.isRequired,
+        onLicensingDataChanged: PropTypes.func.isRequired,
+        featureGroupsList: PropTypes.array,
+        licenseAgreementList: PropTypes.array,
+        isVendorArchived: PropTypes.bool
+    };
 
-       onVendorParamChanged(e) {
-               const selectedIndex = e.target.selectedIndex;
-               const licensingVersion = e.target.options[selectedIndex].value;
-               this.props.onVendorParamChanged({vendorId: this.props.vendorId, licensingVersion}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
-       }
+    onVendorParamChanged(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const licensingVersion = e.target.options[selectedIndex].value;
+        this.props.onVendorParamChanged(
+            { vendorId: this.props.vendorId, licensingVersion },
+            forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+        );
+    }
 
-       onLicensingDataChanged(e) {
-               const selectedIndex = e.target.selectedIndex;
-               const licenseAgreement = e.target.options[selectedIndex].value;
-               this.props.onLicensingDataChanged({licenseAgreement, featureGroups: []});
-       }
+    onLicensingDataChanged(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const licenseAgreement = e.target.options[selectedIndex].value;
+        this.props.onLicensingDataChanged({
+            licenseAgreement,
+            featureGroups: []
+        });
+    }
 
-       render(){
-               return (
-                       <GridSection title={i18n('Licenses')}>
-                               <GridItem>
-                                       <Input
-                                               data-test-id='vsp-licensing-version'
-                                               onChange={e => this.onVendorParamChanged(e)}
-                                               value={this.props.licensingVersion || ''}
-                                               label={i18n('Licensing Version')}
-                                               disabled={this.props.isVendorArchived}
-                                               type='select'>
-                                               {this.props.licensingVersionsList.map(version =>
-                                                       <option
-                                                               key={version.enum}
-                                                               value={version.enum}>{version.title}
-                                                       </option>
-                                               )}
-                                       </Input>
-                               </GridItem>
-                               <GridItem>
-                                       <Input
-                                               data-test-id='vsp-license-agreement'
-                                               label={i18n('License Agreement')}
-                                               type='select'
-                                               disabled={this.props.isVendorArchived}
-                                               value={this.props.licensingData.licenseAgreement ? this.props.licensingData.licenseAgreement : '' }
-                                               onChange={(e) => this.onLicensingDataChanged(e)}>
-                                               <option key='placeholder' value=''>{i18n('Select...')}</option>
-                                               {this.props.licenseAgreementList.map(la => <option value={la.id} key={la.id}>{la.name}</option>)}
-                                       </Input>
-                               </GridItem>
-                               <GridItem>
-                                       {this.props.licensingData.licenseAgreement && (
-                                               <InputOptions
-                                                       data-test-id='vsp-feature-group'
-                                                       type='select'
-                                                       isMultiSelect={true}
-                                                       onInputChange={()=>{}}
-                                                       disabled={this.props.isVendorArchived}
-                                                       onEnumChange={featureGroups => this.props.onFeatureGroupsChanged({featureGroups})}
-                                                       multiSelectedEnum={this.props.licensingData.featureGroups}
-                                                       name='feature-groups'
-                                                       label={i18n('Feature Groups')}
-                                                       clearable={false}
-                                                       values={this.props.featureGroupsList}/>)
-                                       }
-                               </GridItem>
-                       </GridSection>
-               );
-       }
+    render() {
+        return (
+            <GridSection title={i18n('Licenses')}>
+                <GridItem>
+                    <Input
+                        data-test-id="vsp-licensing-version"
+                        onChange={e => this.onVendorParamChanged(e)}
+                        value={this.props.licensingVersion || ''}
+                        label={i18n('Licensing Version')}
+                        disabled={this.props.isVendorArchived}
+                        type="select">
+                        {this.props.licensingVersionsList.map(version => (
+                            <option key={version.enum} value={version.enum}>
+                                {version.title}
+                            </option>
+                        ))}
+                    </Input>
+                </GridItem>
+                <GridItem>
+                    <Input
+                        data-test-id="vsp-license-agreement"
+                        label={i18n('License Agreement')}
+                        type="select"
+                        disabled={this.props.isVendorArchived}
+                        value={
+                            this.props.licensingData.licenseAgreement
+                                ? this.props.licensingData.licenseAgreement
+                                : ''
+                        }
+                        onChange={e => this.onLicensingDataChanged(e)}>
+                        <option key="placeholder" value="">
+                            {i18n('Select...')}
+                        </option>
+                        {this.props.licenseAgreementList.map(la => (
+                            <option value={la.id} key={la.id}>
+                                {la.name}
+                            </option>
+                        ))}
+                    </Input>
+                </GridItem>
+                <GridItem>
+                    {this.props.licensingData.licenseAgreement && (
+                        <InputOptions
+                            data-test-id="vsp-feature-group"
+                            type="select"
+                            isMultiSelect={true}
+                            onInputChange={() => {}}
+                            disabled={this.props.isVendorArchived}
+                            onEnumChange={featureGroups =>
+                                this.props.onFeatureGroupsChanged({
+                                    featureGroups
+                                })
+                            }
+                            multiSelectedEnum={
+                                this.props.licensingData.featureGroups
+                            }
+                            name="feature-groups"
+                            label={i18n('Feature Groups')}
+                            clearable={false}
+                            values={this.props.featureGroupsList}
+                        />
+                    )}
+                </GridItem>
+            </GridSection>
+        );
+    }
 }
-const AvailabilitySection = (props) => (
-       <GridSection title={i18n('Availability')}>
-               <GridItem colSpan={2}>
-                       <Input
-                               data-test-id='vsp-use-availability-zone'
-                               label={i18n('Use Availability Zones for High Availability')}
-                               type='checkbox'
-                               checked={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']}
-                               value={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']}
-                               onChange={(aZone) => props.onQDataChanged({'general/availability/useAvailabilityZonesForHighAvailability' : aZone})} />
-               </GridItem>
-       </GridSection>
+const AvailabilitySection = props => (
+    <GridSection title={i18n('Availability')}>
+        <GridItem colSpan={2}>
+            <Input
+                data-test-id="vsp-use-availability-zone"
+                label={i18n('Use Availability Zones for High Availability')}
+                type="checkbox"
+                checked={
+                    props.dataMap[
+                        'general/availability/useAvailabilityZonesForHighAvailability'
+                    ]
+                }
+                value={
+                    props.dataMap[
+                        'general/availability/useAvailabilityZonesForHighAvailability'
+                    ]
+                }
+                onChange={aZone =>
+                    props.onQDataChanged({
+                        'general/availability/useAvailabilityZonesForHighAvailability': aZone
+                    })
+                }
+            />
+        </GridItem>
+    </GridSection>
 );
-const RegionsSection = (props) => (
-       <GridSection title={i18n('Regions')}>
-               <GridItem>
-                       <InputOptions
-                               data-test-id='vsp-regions'
-                               type='select'
-                               isMultiSelect={true}
-                               onInputChange={()=>{}}
-                               onEnumChange={(regions) => props.onQDataChanged({'general/regionsData/regions' : regions})}
-                               multiSelectedEnum={props.dataMap['general/regionsData/regions']}
-                               name='vsp-regions'
-                               clearable={false}
-                               values={props.genericFieldInfo['general/regionsData/regions'].enum} />
-               </GridItem>
-       </GridSection>
+const RegionsSection = props => (
+    <GridSection title={i18n('Regions')}>
+        <GridItem>
+            <InputOptions
+                data-test-id="vsp-regions"
+                type="select"
+                isMultiSelect={true}
+                onInputChange={() => {}}
+                onEnumChange={regions =>
+                    props.onQDataChanged({
+                        'general/regionsData/regions': regions
+                    })
+                }
+                multiSelectedEnum={props.dataMap['general/regionsData/regions']}
+                name="vsp-regions"
+                clearable={false}
+                values={
+                    props.genericFieldInfo['general/regionsData/regions'].enum
+                }
+            />
+        </GridItem>
+    </GridSection>
 );
-const StorageDataReplicationSection = (props) => (
-       <GridSection title={i18n('Storage Data Replication')}>
-               <GridItem>
-                       <Input
-                               data-test-id='vsp-storage-rep-size'
-                               label={i18n('Storage Replication Size (GB)')}
-                               type='number'
-                               isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].isValid}
-                               errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].errorText}
-                               value={props.dataMap['general/storageDataReplication/storageReplicationSize']}
-                               onChange={(sRep) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSize' : sRep})} />
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='vsp-storage-rep-source'
-                               label={i18n('Storage Replication Source')}
-                               type='text'
-                               isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].isValid}
-                               errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].errorText}
-                               value={props.dataMap['general/storageDataReplication/storageReplicationSource']}
-                               onChange={(sRepSource) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSource' : sRepSource})} />
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='vsp-storage-rep-freq'
-                               label={i18n('Storage Replication Freq. (min)')}
-                               type='number'
-                               isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].isValid}
-                               errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].errorText}
-                               value={props.dataMap['general/storageDataReplication/storageReplicationFrequency']}
-                               onChange={(sRepFreq) => props.onQDataChanged({'general/storageDataReplication/storageReplicationFrequency' : sRepFreq})} />
-               </GridItem>
-               <GridItem>
-                       <Input
-                               data-test-id='vsp-storage-rep-dest'
-                               label={i18n('Storage Replication Destination')}
-                               type='text'
-                               isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].isValid}
-                               errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].errorText}
-                               value={props.dataMap['general/storageDataReplication/storageReplicationDestination']}
-                               onChange={(sRepDest) => props.onQDataChanged({'general/storageDataReplication/storageReplicationDestination' : sRepDest})} />
-               </GridItem>
-       </GridSection>
+const StorageDataReplicationSection = props => (
+    <GridSection title={i18n('Storage Data Replication')}>
+        <GridItem>
+            <Input
+                data-test-id="vsp-storage-rep-size"
+                label={i18n('Storage Replication Size (GB)')}
+                type="number"
+                isValid={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationSize'
+                    ].isValid
+                }
+                errorText={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationSize'
+                    ].errorText
+                }
+                value={
+                    props.dataMap[
+                        'general/storageDataReplication/storageReplicationSize'
+                    ]
+                }
+                onChange={sRep =>
+                    props.onQDataChanged({
+                        'general/storageDataReplication/storageReplicationSize': sRep
+                    })
+                }
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="vsp-storage-rep-source"
+                label={i18n('Storage Replication Source')}
+                type="text"
+                isValid={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationSource'
+                    ].isValid
+                }
+                errorText={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationSource'
+                    ].errorText
+                }
+                value={
+                    props.dataMap[
+                        'general/storageDataReplication/storageReplicationSource'
+                    ]
+                }
+                onChange={sRepSource =>
+                    props.onQDataChanged({
+                        'general/storageDataReplication/storageReplicationSource': sRepSource
+                    })
+                }
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="vsp-storage-rep-freq"
+                label={i18n('Storage Replication Freq. (min)')}
+                type="number"
+                isValid={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationFrequency'
+                    ].isValid
+                }
+                errorText={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationFrequency'
+                    ].errorText
+                }
+                value={
+                    props.dataMap[
+                        'general/storageDataReplication/storageReplicationFrequency'
+                    ]
+                }
+                onChange={sRepFreq =>
+                    props.onQDataChanged({
+                        'general/storageDataReplication/storageReplicationFrequency': sRepFreq
+                    })
+                }
+            />
+        </GridItem>
+        <GridItem>
+            <Input
+                data-test-id="vsp-storage-rep-dest"
+                label={i18n('Storage Replication Destination')}
+                type="text"
+                isValid={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationDestination'
+                    ].isValid
+                }
+                errorText={
+                    props.genericFieldInfo[
+                        'general/storageDataReplication/storageReplicationDestination'
+                    ].errorText
+                }
+                value={
+                    props.dataMap[
+                        'general/storageDataReplication/storageReplicationDestination'
+                    ]
+                }
+                onChange={sRepDest =>
+                    props.onQDataChanged({
+                        'general/storageDataReplication/storageReplicationDestination': sRepDest
+                    })
+                }
+            />
+        </GridItem>
+    </GridSection>
 );
 
 class SoftwareProductDetails extends Component {
+    static propTypes = {
+        vendorName: PropTypes.string,
+        currentSoftwareProduct: PropTypes.shape({
+            id: PropTypes.string,
+            name: PropTypes.string,
+            description: PropTypes.string,
+            category: PropTypes.string,
+            subCategory: PropTypes.string,
+            vendorId: PropTypes.string,
+            vendorName: PropTypes.string,
+            licensingVersion: PropTypes.string,
+            licensingData: PropTypes.shape({
+                licenceAgreement: PropTypes.string,
+                featureGroups: PropTypes.array
+            })
+        }),
+        softwareProductCategories: PropTypes.array,
+        finalizedLicenseModelList: PropTypes.array,
+        licenseAgreementList: PropTypes.array,
+        featureGroupsList: PropTypes.array,
+        onSubmit: PropTypes.func.isRequired,
+        onDataChanged: PropTypes.func.isRequired,
+        onValidityChanged: PropTypes.func.isRequired,
+        qdata: PropTypes.object.isRequired,
+        onQDataChanged: PropTypes.func.isRequired,
+        onVendorParamChanged: PropTypes.func.isRequired
+    };
 
-       static propTypes = {
-               vendorName: PropTypes.string,
-               currentSoftwareProduct: PropTypes.shape({
-                       id: PropTypes.string,
-                       name: PropTypes.string,
-                       description: PropTypes.string,
-                       category: PropTypes.string,
-                       subCategory: PropTypes.string,
-                       vendorId: PropTypes.string,
-                       vendorName: PropTypes.string,
-                       licensingVersion: PropTypes.string,
-                       licensingData: PropTypes.shape({
-                               licenceAgreement: PropTypes.string,
-                               featureGroups: PropTypes.array
-                       })
-               }),
-               softwareProductCategories: PropTypes.array,
-               finalizedLicenseModelList: PropTypes.array,
-               licenseAgreementList: PropTypes.array,
-               featureGroupsList: PropTypes.array,
-               onSubmit: PropTypes.func.isRequired,
-               onDataChanged: PropTypes.func.isRequired,
-               onValidityChanged: PropTypes.func.isRequired,
-               qdata: PropTypes.object.isRequired,
-               onQDataChanged: PropTypes.func.isRequired,
-               onVendorParamChanged: PropTypes.func.isRequired
-       };
-
-       prepareDataForGeneralSection(){
-               let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, currentSoftwareProduct, genericFieldInfo, isVendorArchived, onArchivedVendorRemove} = this.props;
-               let {name, description, vendorId, subCategory, vendorName} = currentSoftwareProduct;            
-               return {
-                       name,
-                       description,
-                       vendorId,
-                       subCategory,
-                       softwareProductCategories,
-                       finalizedLicenseModelList,
-                       onDataChanged,
-                       onVendorParamChanged: args => this.onVendorParamChanged(args),
-                       onSelectSubCategory: args => this.onSelectSubCategory(args),
-                       genericFieldInfo,
-                       vendorName,
-                       isVendorArchived,
-                       onArchivedVendorRemove
-               };
-
-       }
+    prepareDataForGeneralSection() {
+        let {
+            softwareProductCategories,
+            finalizedLicenseModelList,
+            onDataChanged,
+            currentSoftwareProduct,
+            genericFieldInfo,
+            isVendorArchived,
+            onArchivedVendorRemove
+        } = this.props;
+        let {
+            name,
+            description,
+            vendorId,
+            subCategory,
+            vendorName
+        } = currentSoftwareProduct;
+        return {
+            name,
+            description,
+            vendorId,
+            subCategory,
+            softwareProductCategories,
+            finalizedLicenseModelList,
+            onDataChanged,
+            onVendorParamChanged: args => this.onVendorParamChanged(args),
+            onSelectSubCategory: args => this.onSelectSubCategory(args),
+            genericFieldInfo,
+            vendorName,
+            isVendorArchived,
+            onArchivedVendorRemove
+        };
+    }
 
-       prepareDataForLicensesSection(){
-               let { featureGroupsList, licenseAgreementList, currentSoftwareProduct, isVendorArchived} = this.props;
-               let {vendorId, licensingVersion, licensingData = {}} = currentSoftwareProduct;
-               return {
-                       onVendorParamChanged: args => this.onVendorParamChanged(args),
-                       vendorId,
-                       licensingVersion,
-                       licensingVersionsList: this.buildLicensingVersionsListItems(),
-                       licensingData,
-                       onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args),
-                       onLicensingDataChanged: args => this.onLicensingDataChanged(args),
-                       featureGroupsList,
-                       licenseAgreementList,
-                       isVendorArchived
-               };
+    prepareDataForLicensesSection() {
+        let {
+            featureGroupsList,
+            licenseAgreementList,
+            currentSoftwareProduct,
+            isVendorArchived
+        } = this.props;
+        let {
+            vendorId,
+            licensingVersion,
+            licensingData = {}
+        } = currentSoftwareProduct;
+        return {
+            onVendorParamChanged: args => this.onVendorParamChanged(args),
+            vendorId,
+            licensingVersion,
+            licensingVersionsList: this.buildLicensingVersionsListItems(),
+            licensingData,
+            onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args),
+            onLicensingDataChanged: args => this.onLicensingDataChanged(args),
+            featureGroupsList,
+            licenseAgreementList,
+            isVendorArchived
+        };
+    }
 
-       }
+    render() {
+        let { currentSoftwareProduct } = this.props;
+        let { qdata, onQDataChanged, dataMap, qGenericFieldInfo } = this.props;
+        let { isReadOnlyMode } = this.props;
 
-       render() {
-               let {currentSoftwareProduct} = this.props;
-               let {qdata, onQDataChanged, dataMap, qGenericFieldInfo} = this.props;
-               let {isReadOnlyMode} = this.props;
+        return (
+            <div className="vsp-details-page">
+                <Form
+                    ref={validationForm =>
+                        (this.validationForm = validationForm)
+                    }
+                    className="vsp-general-tab"
+                    hasButtons={false}
+                    formReady={null}
+                    isValid={this.props.isFormValid}
+                    onSubmit={() =>
+                        this.props.onSubmit(currentSoftwareProduct, qdata)
+                    }
+                    onValidityChanged={isValidityData =>
+                        this.props.onValidityChanged(isValidityData)
+                    }
+                    isReadOnlyMode={isReadOnlyMode}>
+                    <GeneralSection {...this.prepareDataForGeneralSection()} />
+                    <LicensesSection
+                        {...this.prepareDataForLicensesSection()}
+                    />
+                    <AvailabilitySection
+                        onQDataChanged={onQDataChanged}
+                        dataMap={dataMap}
+                    />
+                    <RegionsSection
+                        onQDataChanged={onQDataChanged}
+                        dataMap={dataMap}
+                        genericFieldInfo={qGenericFieldInfo}
+                    />
+                    <StorageDataReplicationSection
+                        onQDataChanged={onQDataChanged}
+                        dataMap={dataMap}
+                        genericFieldInfo={qGenericFieldInfo}
+                    />
+                </Form>
+            </div>
+        );
+    }
 
-               return (
-               <div className='vsp-details-page'>
-                               <Form
-                                       ref={(validationForm) => this.validationForm = validationForm}
-                                       className='vsp-general-tab'
-                                       hasButtons={false}
-                                       formReady={null}
-                                       isValid={this.props.isFormValid}
-                                       onSubmit={() => this.props.onSubmit(currentSoftwareProduct, qdata)}
-                                       onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)}
-                                       isReadOnlyMode={isReadOnlyMode}>
-                                       <GeneralSection {...this.prepareDataForGeneralSection()}/>
-                                       <LicensesSection {...this.prepareDataForLicensesSection()}/>
-                                       <AvailabilitySection onQDataChanged={onQDataChanged} dataMap={dataMap} />
-                                       <RegionsSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} />
-                                       <StorageDataReplicationSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} />
-                               </Form>
-                       </div>
-               );
-       }
+    onVendorParamChanged({ vendorId, licensingVersion }) {
+        let { finalizedLicenseModelList, onVendorParamChanged } = this.props;
+        if (!licensingVersion) {
+            const licensingVersionsList = this.buildLicensingVersionsListItems();
+            licensingVersion = licensingVersionsList[0].enum;
+        }
 
-       onVendorParamChanged({vendorId, licensingVersion}) {
-               
-               let {finalizedLicenseModelList, onVendorParamChanged} = this.props;
-               if(!licensingVersion) {
-                       const licensingVersionsList = this.buildLicensingVersionsListItems();
-                       licensingVersion = licensingVersionsList[0].enum;
-               }
-               
-               if (!vendorId) {
-                        vendorId = finalizedLicenseModelList[0].id;
-               }
-               
-               let vendorName = finalizedLicenseModelList.find(licenseModelItem => licenseModelItem.id === vendorId).name || '';
-               let deltaData = {
-                       vendorId,
-                       vendorName,
-                       licensingVersion,
-                       licensingData: {}
-               };
+        if (!vendorId) {
+            vendorId = finalizedLicenseModelList[0].id;
+        }
 
-               onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
+        let vendorName =
+            finalizedLicenseModelList.find(
+                licenseModelItem => licenseModelItem.id === vendorId
+            ).name || '';
+        let deltaData = {
+            vendorId,
+            vendorName,
+            licensingVersion,
+            licensingData: {}
+        };
 
-       }
+        onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
+    }
 
-       buildLicensingVersionsListItems() {
-               let {licensingVersionsList} = this.props;
+    buildLicensingVersionsListItems() {
+        let { licensingVersionsList } = this.props;
 
-               let licensingVersionsListItems = [{
-                       enum: '',
-                       title: i18n('Select...')
-               }];
+        let licensingVersionsListItems = [
+            {
+                enum: '',
+                title: i18n('Select...')
+            }
+        ];
 
-               return licensingVersionsListItems.concat(licensingVersionsList.map(version => ({enum: version.id, title: version.name})));
-       }
+        return licensingVersionsListItems.concat(
+            licensingVersionsList.map(version => ({
+                enum: version.id,
+                title: version.name
+            }))
+        );
+    }
 
-       onFeatureGroupsChanged({featureGroups}) {
-               this.onLicensingDataChanged({featureGroups});
-       }
+    onFeatureGroupsChanged({ featureGroups }) {
+        this.onLicensingDataChanged({ featureGroups });
+    }
 
-       onLicensingDataChanged(deltaData) {
-               this.props.onDataChanged({
-                       licensingData: {
-                               ...this.props.currentSoftwareProduct.licensingData,
-                               ...deltaData
-                       }
-               }, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
-       }
+    onLicensingDataChanged(deltaData) {
+        this.props.onDataChanged(
+            {
+                licensingData: {
+                    ...this.props.currentSoftwareProduct.licensingData,
+                    ...deltaData
+                }
+            },
+            forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+        );
+    }
 
-       onSelectSubCategory(subCategory) {
-               let {softwareProductCategories, onDataChanged} = this.props;
-               let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories);
-               onDataChanged({category, subCategory}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
-       }
+    onSelectSubCategory(subCategory) {
+        let { softwareProductCategories, onDataChanged } = this.props;
+        let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(
+            subCategory,
+            softwareProductCategories
+        );
+        onDataChanged(
+            { category, subCategory },
+            forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
+        );
+    }
 
-       save(){
-               return this.validationForm.handleFormSubmit(new Event('dummy'));
-       }
+    save() {
+        return this.validationForm.handleFormSubmit(new Event('dummy'));
+    }
 }
 
 export default SoftwareProductDetails;
index 64e0d56..34bfcee 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
 import LandingPageView from './SoftwareProductLandingPageView.jsx';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {onboardingMethod} from '../SoftwareProductConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { onboardingMethod } from '../SoftwareProductConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
-import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
-
+import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 
 export const mapStateToProps = ({
-       softwareProduct,
-       licenseModel: {licenseAgreement},
+    softwareProduct,
+    licenseModel: { licenseAgreement }
 }) => {
-       let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents, softwareProductCategories = [], } = softwareProduct;
-       let {licensingData = {}} = currentSoftwareProduct;
-       let {licenseAgreementList} = licenseAgreement;
-       let {componentsList} = softwareProductComponents;
-       let licenseAgreementName = licenseAgreementList.find(la => la.id === licensingData.licenseAgreement);
-       if (licenseAgreementName) {
-               licenseAgreementName = licenseAgreementName.name;
-       } else if (licenseAgreementList.length === 0) { // otherwise the state of traingle svgicon will be updated post unmounting
-               licenseAgreementName = null;
-       }
-
-       let categoryName = '', subCategoryName = '', fullCategoryDisplayName = '';
-       const category = softwareProductCategories.find(ca => ca.uniqueId === currentSoftwareProduct.category);
-       if (category) {
-               categoryName = category.name;
-               const subcategories = category.subcategories || [];
-               const subcat = subcategories.find(sc => sc.uniqueId === currentSoftwareProduct.subCategory);
-               subCategoryName = subcat && subcat.name ? subcat.name : '';
-       }
-       fullCategoryDisplayName = `${subCategoryName} (${categoryName})`;
+    let {
+        softwareProductEditor: { data: currentSoftwareProduct = {} },
+        softwareProductComponents,
+        softwareProductCategories = []
+    } = softwareProduct;
+    let { licensingData = {} } = currentSoftwareProduct;
+    let { licenseAgreementList } = licenseAgreement;
+    let { componentsList } = softwareProductComponents;
+    let licenseAgreementName = licenseAgreementList.find(
+        la => la.id === licensingData.licenseAgreement
+    );
+    if (licenseAgreementName) {
+        licenseAgreementName = licenseAgreementName.name;
+    } else if (licenseAgreementList.length === 0) {
+        // otherwise the state of traingle svgicon will be updated post unmounting
+        licenseAgreementName = null;
+    }
 
+    let categoryName = '',
+        subCategoryName = '',
+        fullCategoryDisplayName = '';
+    const category = softwareProductCategories.find(
+        ca => ca.uniqueId === currentSoftwareProduct.category
+    );
+    if (category) {
+        categoryName = category.name;
+        const subcategories = category.subcategories || [];
+        const subcat = subcategories.find(
+            sc => sc.uniqueId === currentSoftwareProduct.subCategory
+        );
+        subCategoryName = subcat && subcat.name ? subcat.name : '';
+    }
+    fullCategoryDisplayName = `${subCategoryName} (${categoryName})`;
 
-       return {
-               currentSoftwareProduct: {
-                       ...currentSoftwareProduct,
-                       licenseAgreementName,
-                       fullCategoryDisplayName                                         
-               },              
-               componentsList,
-               isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
-       };
+    return {
+        currentSoftwareProduct: {
+            ...currentSoftwareProduct,
+            licenseAgreementName,
+            fullCategoryDisplayName
+        },
+        componentsList,
+        isManual:
+            currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
+    };
 };
 
-const mapActionsToProps = (dispatch, {version}) => {
-       return {
-               onDetailsSelect: ({id: softwareProductId}) =>
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, screenType: screenTypes.SOFTWARE_PRODUCT,
-                               props: {softwareProductId, version}
-                       }),
-               onCandidateInProcess: (softwareProductId) => ScreensHelper.loadScreen(dispatch, {
-                       screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, screenType: screenTypes.SOFTWARE_PRODUCT,
-                       props: {softwareProductId, version}
-               }),     
-               onUpload: (softwareProductId, formData) =>
-                       SoftwareProductActionHelper.uploadFile(dispatch, {
-                               softwareProductId,
-                               formData,
-                               failedNotificationTitle: i18n('Upload validation failed'),
-                               version
-                       }),
+const mapActionsToProps = (dispatch, { version }) => {
+    return {
+        onDetailsSelect: ({ id: softwareProductId }) =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: { softwareProductId, version }
+            }),
+        onCandidateInProcess: softwareProductId =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: { softwareProductId, version }
+            }),
+        onUpload: (softwareProductId, formData) =>
+            SoftwareProductActionHelper.uploadFile(dispatch, {
+                softwareProductId,
+                formData,
+                failedNotificationTitle: i18n('Upload validation failed'),
+                version
+            }),
 
-               onUploadConfirmation: (softwareProductId, formData) =>
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                               data:{
-                                       msg: i18n('Upload will erase existing data. Do you want to continue?'),
-                                       confirmationButtonText: i18n('Continue'),
-                                       title: i18n('Warning'),
-                                       onConfirmed: ()=>SoftwareProductActionHelper.uploadFile(dispatch, {
-                                               softwareProductId,
-                                               formData,
-                                               failedNotificationTitle: i18n('Upload validation failed'),
-                                               version
-                                       }),
-                                       onDeclined: () => dispatch({
-                                               type: modalActionTypes.GLOBAL_MODAL_CLOSE
-                                       })
-                               }
-                       }),
+        onUploadConfirmation: (softwareProductId, formData) =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n(
+                        'Upload will erase existing data. Do you want to continue?'
+                    ),
+                    confirmationButtonText: i18n('Continue'),
+                    title: i18n('Warning'),
+                    onConfirmed: () =>
+                        SoftwareProductActionHelper.uploadFile(dispatch, {
+                            softwareProductId,
+                            formData,
+                            failedNotificationTitle: i18n(
+                                'Upload validation failed'
+                            ),
+                            version
+                        }),
+                    onDeclined: () =>
+                        dispatch({
+                            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+                        })
+                }
+            }),
 
-               onInvalidFileSizeUpload: () => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_ERROR,
-                       data: {
-                               title: i18n('Upload Failed'),
-                               confirmationButtonText: i18n('Continue'),
-                               msg: i18n('no zip or csar file was uploaded or expected file doesn\'t exist')
-                       }
-               }),
-               onComponentSelect: ({id: softwareProductId, componentId}) => ScreensHelper.loadScreen(dispatch, {
-                       screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, screenType: screenTypes.SOFTWARE_PRODUCT,
-                       props: {softwareProductId, version, componentId}
-               }),
-               /** for the next version */
-               onAddComponent: () => SoftwareProductActionHelper.addComponent(dispatch)
-       };
+        onInvalidFileSizeUpload: () =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_ERROR,
+                data: {
+                    title: i18n('Upload Failed'),
+                    confirmationButtonText: i18n('Continue'),
+                    msg: i18n(
+                        "no zip or csar file was uploaded or expected file doesn't exist"
+                    )
+                }
+            }),
+        onComponentSelect: ({ id: softwareProductId, componentId }) =>
+            ScreensHelper.loadScreen(dispatch, {
+                screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL,
+                screenType: screenTypes.SOFTWARE_PRODUCT,
+                props: { softwareProductId, version, componentId }
+            }),
+        /** for the next version */
+        onAddComponent: () => SoftwareProductActionHelper.addComponent(dispatch)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(LandingPageView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(LandingPageView);
index a73a849..bc8a2be 100644 (file)
@@ -18,7 +18,6 @@ import PropTypes from 'prop-types';
 import classnames from 'classnames';
 import Dropzone from 'react-dropzone';
 
-
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import DraggableUploadFileBox from 'nfvo-components/fileupload/DraggableUploadFileBox.jsx';
 
@@ -26,192 +25,237 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import SoftwareProductComponentsList from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js';
 
 const SoftwareProductPropType = PropTypes.shape({
-       name: PropTypes.string,
-       description: PropTypes.string,
-       version: PropTypes.string,
-       id: PropTypes.string,
-       categoryId: PropTypes.string,
-       vendorId: PropTypes.string,
-       status: PropTypes.string,
-       licensingData: PropTypes.object,
-       validationData: PropTypes.object
+    name: PropTypes.string,
+    description: PropTypes.string,
+    version: PropTypes.string,
+    id: PropTypes.string,
+    categoryId: PropTypes.string,
+    vendorId: PropTypes.string,
+    status: PropTypes.string,
+    licensingData: PropTypes.object,
+    validationData: PropTypes.object
 });
 
 const ComponentPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       displayName: PropTypes.string,
-       description: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    displayName: PropTypes.string,
+    description: PropTypes.string
 });
 
 class SoftwareProductLandingPageView extends React.Component {
+    state = {
+        fileName: '',
+        dragging: false,
+        files: []
+    };
+
+    static propTypes = {
+        currentSoftwareProduct: SoftwareProductPropType,
+        isReadOnlyMode: PropTypes.bool,
+        componentsList: PropTypes.arrayOf(ComponentPropType),
+        version: PropTypes.object,
+        onDetailsSelect: PropTypes.func,
+        onUpload: PropTypes.func,
+        onUploadConfirmation: PropTypes.func,
+        onInvalidFileSizeUpload: PropTypes.func,
+        onComponentSelect: PropTypes.func,
+        onAddComponent: PropTypes.func
+    };
+    componentDidMount() {
+        const { onCandidateInProcess, currentSoftwareProduct } = this.props;
+        if (currentSoftwareProduct.candidateOnboardingOrigin) {
+            onCandidateInProcess(currentSoftwareProduct.id);
+        }
+    }
+    render() {
+        let {
+            currentSoftwareProduct,
+            isReadOnlyMode,
+            isManual,
+            onDetailsSelect
+        } = this.props;
+        return (
+            <div className="software-product-landing-wrapper">
+                <Dropzone
+                    className={classnames('software-product-landing-view', {
+                        'active-dragging': this.state.dragging
+                    })}
+                    onDrop={files =>
+                        this.handleImportSubmit(files, isReadOnlyMode, isManual)
+                    }
+                    onDragEnter={() =>
+                        this.handleOnDragEnter(isReadOnlyMode, isManual)
+                    }
+                    onDragLeave={() => this.setState({ dragging: false })}
+                    multiple={false}
+                    disableClick={true}
+                    ref="fileInput"
+                    name="fileInput"
+                    accept=".zip, .csar">
+                    <div className="draggable-wrapper">
+                        <div className="software-product-landing-view-top">
+                            <div className="row">
+                                <ProductSummary
+                                    currentSoftwareProduct={
+                                        currentSoftwareProduct
+                                    }
+                                    onDetailsSelect={onDetailsSelect}
+                                />
+                                {this.renderProductDetails(
+                                    isManual,
+                                    isReadOnlyMode
+                                )}
+                            </div>
+                        </div>
+                    </div>
+                </Dropzone>
+                <SoftwareProductComponentsList />
+            </div>
+        );
+    }
+
+    handleOnDragEnter(isReadOnlyMode, isManual) {
+        if (!isReadOnlyMode && !isManual) {
+            this.setState({ dragging: true });
+        }
+    }
+
+    renderProductDetails(isManual, isReadOnlyMode) {
+        return (
+            <div className="details-panel">
+                {!isManual && (
+                    <div>
+                        <div className="software-product-landing-view-heading-title">
+                            {i18n('Software Product Attachments')}
+                        </div>
+                        <DraggableUploadFileBox
+                            dataTestId="upload-btn"
+                            isReadOnlyMode={isReadOnlyMode}
+                            className={classnames(
+                                'software-product-landing-view-top-block-col-upl',
+                                { disabled: isReadOnlyMode }
+                            )}
+                            onClick={() => this.refs.fileInput.open()}
+                        />
+                    </div>
+                )}
+            </div>
+        );
+    }
+
+    handleImportSubmit(files, isReadOnlyMode, isManual) {
+        if (isReadOnlyMode || isManual) {
+            return;
+        }
+        if (files[0] && files[0].size) {
+            this.setState({
+                fileName: files[0].name,
+                dragging: false,
+                complete: '0'
+            });
+            this.startUploading(files);
+        } else {
+            this.setState({
+                dragging: false
+            });
+            this.props.onInvalidFileSizeUpload();
+        }
+    }
 
-       state = {
-
-               fileName: '',
-               dragging: false,
-               files: []
-       };
-
-       static propTypes = {
-               currentSoftwareProduct: SoftwareProductPropType,
-               isReadOnlyMode: PropTypes.bool,
-               componentsList: PropTypes.arrayOf(ComponentPropType),
-               version: PropTypes.object,
-               onDetailsSelect: PropTypes.func,
-               onUpload: PropTypes.func,
-               onUploadConfirmation: PropTypes.func,
-               onInvalidFileSizeUpload: PropTypes.func,
-               onComponentSelect: PropTypes.func,
-               onAddComponent: PropTypes.func
-       };
-       componentDidMount() {
-               const {onCandidateInProcess, currentSoftwareProduct} = this.props;
-               if (currentSoftwareProduct.candidateOnboardingOrigin) {
-                       onCandidateInProcess(currentSoftwareProduct.id);
-               }
-       }
-       render() {
-               let {currentSoftwareProduct, isReadOnlyMode, isManual, onDetailsSelect} =  this.props;
-               return (
-                       <div className='software-product-landing-wrapper'>
-                               <Dropzone
-                                       className={classnames('software-product-landing-view', {'active-dragging': this.state.dragging})}
-                                       onDrop={files => this.handleImportSubmit(files, isReadOnlyMode, isManual)}
-                                       onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode, isManual)}
-                                       onDragLeave={() => this.setState({dragging:false})}
-                                       multiple={false}
-                                       disableClick={true}
-                                       ref='fileInput'
-                                       name='fileInput'
-                                       accept='.zip, .csar'>
-                                       <div className='draggable-wrapper'>
-                                               <div className='software-product-landing-view-top'>
-                                                       <div className='row'>
-                                                               <ProductSummary currentSoftwareProduct={currentSoftwareProduct} onDetailsSelect={onDetailsSelect} />
-                                                               {this.renderProductDetails(isManual, isReadOnlyMode)}
-                                                       </div>
-                                               </div>
-                                       </div>
-                               </Dropzone>
-                               <SoftwareProductComponentsList/>
-                       </div>
-               );
-       }
-
-       handleOnDragEnter(isReadOnlyMode, isManual) {
-               if (!isReadOnlyMode && !isManual) {
-                       this.setState({dragging: true});
-               }
-       }
-
-       renderProductDetails(isManual, isReadOnlyMode) {
-               return (
-                       <div className='details-panel'>
-                               { !isManual && <div>
-                                       <div className='software-product-landing-view-heading-title'>{i18n('Software Product Attachments')}</div>
-                                               <DraggableUploadFileBox
-                                                       dataTestId='upload-btn'
-                                                       isReadOnlyMode={isReadOnlyMode}
-                                                       className={classnames('software-product-landing-view-top-block-col-upl', {'disabled': isReadOnlyMode})}
-                                                       onClick={() => this.refs.fileInput.open()}/>
-                                       </div>
-                               }
-                       </div>
-               );
-       }
-
-       handleImportSubmit(files, isReadOnlyMode, isManual) {
-               if (isReadOnlyMode || isManual) {
-                       return;
-               }
-               if (files[0] && files[0].size) {
-                       this.setState({
-                               fileName: files[0].name,
-                               dragging: false,
-                               complete: '0',
-                       });
-                       this.startUploading(files);
-               }
-               else {
-                       this.setState({
-                               dragging: false
-                       });
-                       this.props.onInvalidFileSizeUpload();
-               }
-
-       }
-
-       startUploading(files) {
-               let {onUpload, currentSoftwareProduct, onUploadConfirmation} = this.props;
-
-               let {validationData} = currentSoftwareProduct;
-
-               if (!(files && files.length)) {
-                       return;
-               }
-               let file = files[0];
-               let formData = new FormData();
-               formData.append('upload', file);
-               this.refs.fileInput.value = '';
-
-               if (validationData) {
-                       onUploadConfirmation(currentSoftwareProduct.id, formData);
-               }else {
-                       onUpload(currentSoftwareProduct.id, formData);
-               }
-
-       }
+    startUploading(files) {
+        let {
+            onUpload,
+            currentSoftwareProduct,
+            onUploadConfirmation
+        } = this.props;
+
+        let { validationData } = currentSoftwareProduct;
+
+        if (!(files && files.length)) {
+            return;
+        }
+        let file = files[0];
+        let formData = new FormData();
+        formData.append('upload', file);
+        this.refs.fileInput.value = '';
+
+        if (validationData) {
+            onUploadConfirmation(currentSoftwareProduct.id, formData);
+        } else {
+            onUpload(currentSoftwareProduct.id, formData);
+        }
+    }
 }
 
-const ProductSummary = ({currentSoftwareProduct, onDetailsSelect}) => {
-       let {name = '', description = '', vendorName = '', fullCategoryDisplayName = '', licenseAgreementName = ''}  = currentSoftwareProduct;
-       return (
-               <div className='details-panel'>
-                       <div className='software-product-landing-view-heading-title'>{i18n('Software Product Details')}</div>
-                       <div
-                               className='software-product-landing-view-top-block clickable'
-                               onClick={() => onDetailsSelect(currentSoftwareProduct)}>
-                               <div className='details-container'>
-                                       <div className='single-detail-section title-section'>
-                                               <div className='single-detail-section title-text'>
-                                                       {name}
-                                               </div>
-                                       </div>
-                                       <div className='details-section'>
-                                               <div className='multiple-details-section'>
-                                                       <div className='detail-col' >
-                                                               <div className='title'>{i18n('Vendor')}</div>
-                                                               <div className='description'>{vendorName}</div>
-                                                       </div>
-                                                       <div className='detail-col'>
-                                                               <div className='title'>{i18n('Category')}</div>
-                                                               <div className='description'>{fullCategoryDisplayName}</div>
-                                                       </div>
-                                                       <div className='detail-col'>
-                                                               <div className='title extra-large'>{i18n('License Agreement')}</div>
-                                                               <div className='description'>
-                                                                       <LicenseAgreement licenseAgreementName={licenseAgreementName}/>
-                                                               </div>
-                                                       </div>
-                                               </div>
-                                               <div className='single-detail-section'>
-                                                       <div className='title'>{i18n('Description')}</div>
-                                                       <div className='description'>{description}</div>
-                                               </div>
-                                       </div>
-                               </div>
-                       </div>
-               </div>
-       );
+const ProductSummary = ({ currentSoftwareProduct, onDetailsSelect }) => {
+    let {
+        name = '',
+        description = '',
+        vendorName = '',
+        fullCategoryDisplayName = '',
+        licenseAgreementName = ''
+    } = currentSoftwareProduct;
+    return (
+        <div className="details-panel">
+            <div className="software-product-landing-view-heading-title">
+                {i18n('Software Product Details')}
+            </div>
+            <div
+                className="software-product-landing-view-top-block clickable"
+                onClick={() => onDetailsSelect(currentSoftwareProduct)}>
+                <div className="details-container">
+                    <div className="single-detail-section title-section">
+                        <div className="single-detail-section title-text">
+                            {name}
+                        </div>
+                    </div>
+                    <div className="details-section">
+                        <div className="multiple-details-section">
+                            <div className="detail-col">
+                                <div className="title">{i18n('Vendor')}</div>
+                                <div className="description">{vendorName}</div>
+                            </div>
+                            <div className="detail-col">
+                                <div className="title">{i18n('Category')}</div>
+                                <div className="description">
+                                    {fullCategoryDisplayName}
+                                </div>
+                            </div>
+                            <div className="detail-col">
+                                <div className="title extra-large">
+                                    {i18n('License Agreement')}
+                                </div>
+                                <div className="description">
+                                    <LicenseAgreement
+                                        licenseAgreementName={
+                                            licenseAgreementName
+                                        }
+                                    />
+                                </div>
+                            </div>
+                        </div>
+                        <div className="single-detail-section">
+                            <div className="title">{i18n('Description')}</div>
+                            <div className="description">{description}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    );
 };
 
-
-const LicenseAgreement = ({licenseAgreementName}) => {
-       if (!licenseAgreementName) {
-               return (<div className='missing-license'><SVGIcon color='warning' name='exclamationTriangleFull'/><div className='warning-text'>{i18n('Missing')}</div></div>);
-       }
-       return <div>{licenseAgreementName}</div>;
+const LicenseAgreement = ({ licenseAgreementName }) => {
+    if (!licenseAgreementName) {
+        return (
+            <div className="missing-license">
+                <SVGIcon color="warning" name="exclamationTriangleFull" />
+                <div className="warning-text">{i18n('Missing')}</div>
+            </div>
+        );
+    }
+    return <div>{licenseAgreementName}</div>;
 };
 
 export default SoftwareProductLandingPageView;
index 6161ead..27dd471 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SoftwareProductNetworksView from './SoftwareProductNetworksView.jsx';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductNetworks: {networksList = []}} = softwareProduct;
-       return {networksList};
+export const mapStateToProps = ({ softwareProduct }) => {
+    let { softwareProductNetworks: { networksList = [] } } = softwareProduct;
+    return { networksList };
 };
 
-export default connect(mapStateToProps, null, null, {withRef: true})(SoftwareProductNetworksView);
-
+export default connect(mapStateToProps, null, null, { withRef: true })(
+    SoftwareProductNetworksView
+);
index 4cb460e..388c641 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductNetworksConstants.js';
+import { actionTypes } from './SoftwareProductNetworksConstants.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 
 function baseUrl(vspId, version) {
-       let {id: versionId} = version;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/networks`;
+    let { id: versionId } = version;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/networks`;
 }
 
-
 function fetchNetworksList(softwareProductId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
 }
 
 const SoftwareProductNetworksActionHelper = {
-       fetchNetworksList(dispatch, {softwareProductId, version}) {
-               return fetchNetworksList(softwareProductId, version).then(response => {
-                       dispatch({
-                               type: actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS,
-                               networksList: response.results
-                       });
-               });
-       }
+    fetchNetworksList(dispatch, { softwareProductId, version }) {
+        return fetchNetworksList(softwareProductId, version).then(response => {
+            dispatch({
+                type: actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS,
+                networksList: response.results
+            });
+        });
+    }
 };
 
-export  default SoftwareProductNetworksActionHelper;
+export default SoftwareProductNetworksActionHelper;
index e7c2fcb..796de82 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductNetworksConstants.js';
+import { actionTypes } from './SoftwareProductNetworksConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS:
-                       return [...action.networksList];
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS:
+            return [...action.networksList];
+        default:
+            return state;
+    }
 };
index e8c365f..458f319 100644 (file)
@@ -22,73 +22,76 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js
 import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
 
 class SoftwareProductNetworksView extends React.Component {
+    static propTypes = {
+        networksList: PropTypes.arrayOf(
+            PropTypes.shape({
+                id: PropTypes.string.isRequired,
+                name: PropTypes.string.isRequired,
+                dhcp: PropTypes.bool.isRequired
+            })
+        ).isRequired,
+        isReadOnlyMode: PropTypes.bool.isRequired
+    };
 
-       static propTypes = {
-               networksList: PropTypes.arrayOf(PropTypes.shape({
-                       id: PropTypes.string.isRequired,
-                       name: PropTypes.string.isRequired,
-                       dhcp: PropTypes.bool.isRequired
-               })).isRequired,
-               isReadOnlyMode: PropTypes.bool.isRequired
-       };
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
+    render() {
+        const { localFilter } = this.state;
+        const { isReadOnlyMode } = this.props;
 
-       render() {
-               const {localFilter} = this.state;
-               const {isReadOnlyMode} = this.props;
+        return (
+            <div className="vsp-networks-page">
+                <ListEditorView
+                    title={i18n('Networks')}
+                    filterValue={localFilter}
+                    placeholder={i18n('Filter Networks')}
+                    onFilter={value => this.setState({ localFilter: value })}
+                    twoColumns>
+                    {this.filterList().map(network =>
+                        this.renderNetworksListItem({ network, isReadOnlyMode })
+                    )}
+                </ListEditorView>
+            </div>
+        );
+    }
 
-               return (
-                       <div className='vsp-networks-page'>
-                               <ListEditorView
-                                       title={i18n('Networks')}
-                                       filterValue={localFilter}
-                                       placeholder={i18n('Filter Networks')}
-                                       onFilter={value => this.setState({localFilter: value})}
-                                       twoColumns>
-                                       {this.filterList().map(network => this.renderNetworksListItem({network, isReadOnlyMode}))}
-                               </ListEditorView>
-                       </div>
-               );
-       }
+    renderNetworksListItem({ network, isReadOnlyMode }) {
+        let { id, name, dhcp } = network;
+        return (
+            <ListEditorItemView
+                key={id}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}>
+                <ListEditorItemViewField>
+                    <div className="name">{name}</div>
+                </ListEditorItemViewField>
+                <ListEditorItemViewField>
+                    <div className="details">
+                        <div className="title">{i18n('DHCP')}</div>
+                        <div className="artifact-name">
+                            {dhcp ? i18n('YES') : i18n('NO')}
+                        </div>
+                    </div>
+                </ListEditorItemViewField>
+            </ListEditorItemView>
+        );
+    }
 
-       renderNetworksListItem({network, isReadOnlyMode}) {
-               let {id, name, dhcp} = network;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}>
+    filterList() {
+        let { networksList } = this.props;
 
-                               <ListEditorItemViewField>
-                                       <div className='name'>{name}</div>
-                               </ListEditorItemViewField>
-                               <ListEditorItemViewField>
-                                       <div className='details'>
-                                               <div className='title'>{i18n('DHCP')}</div>
-                                               <div className='artifact-name'>{dhcp ? i18n('YES') : i18n('NO')}</div>
-                                       </div>
-                               </ListEditorItemViewField>
-                       </ListEditorItemView>
-               );
-       }
-
-       filterList() {
-               let {networksList} = this.props;
-
-               let {localFilter} = this.state;
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return networksList.filter(({name = ''}) => {
-                               return escape(name).match(filter);
-                       });
-               }
-               else {
-                       return networksList;
-               }
-       }
+        let { localFilter } = this.state;
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return networksList.filter(({ name = '' }) => {
+                return escape(name).match(filter);
+            });
+        } else {
+            return networksList;
+        }
+    }
 }
 
 export default SoftwareProductNetworksView;
index aa39c87..cee46ab 100644 (file)
@@ -20,80 +20,86 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
 import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
 
-
 class SoftwareProductProcessesListView extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
-
-       static propTypes = {
-               onAddProcess: PropTypes.func.isRequired,
-               onEditProcess: PropTypes.func.isRequired,
-               onDeleteProcess: PropTypes.func.isRequired,
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               currentSoftwareProduct:PropTypes.object,
-               addButtonTitle: PropTypes.string
-       };
-
-       render() {
-               const {localFilter} = this.state;
-               let {onAddProcess, isReadOnlyMode, addButtonTitle} = this.props;
+    static propTypes = {
+        onAddProcess: PropTypes.func.isRequired,
+        onEditProcess: PropTypes.func.isRequired,
+        onDeleteProcess: PropTypes.func.isRequired,
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        currentSoftwareProduct: PropTypes.object,
+        addButtonTitle: PropTypes.string
+    };
 
-               return (
-                       <ListEditorView
-                               plusButtonTitle={addButtonTitle}
-                               filterValue={localFilter}
-                               placeholder={i18n('Filter Process')}
-                               onAdd={onAddProcess}
-                               isReadOnlyMode={isReadOnlyMode}
-                               title={i18n('Process Details')}
-                               onFilter={value => this.setState({localFilter: value})}>
-                               {this.filterList().map(processes => this.renderProcessListItem(processes, isReadOnlyMode))}
-                       </ListEditorView>);
-       }
+    render() {
+        const { localFilter } = this.state;
+        let { onAddProcess, isReadOnlyMode, addButtonTitle } = this.props;
 
-       renderProcessListItem(process, isReadOnlyMode) {
-               let {id, name, description, artifactName = ''} = process;
-               let {currentSoftwareProduct: {version}, onEditProcess, onDeleteProcess} =  this.props;
-               return (
-                       <ListEditorItemView
-                               key={id}
-                               className='list-editor-item-view'
-                               isReadOnlyMode={isReadOnlyMode}
-                               onSelect={() => onEditProcess(process)}
-                               onDelete={() => onDeleteProcess(process, version)}>
+        return (
+            <ListEditorView
+                plusButtonTitle={addButtonTitle}
+                filterValue={localFilter}
+                placeholder={i18n('Filter Process')}
+                onAdd={onAddProcess}
+                isReadOnlyMode={isReadOnlyMode}
+                title={i18n('Process Details')}
+                onFilter={value => this.setState({ localFilter: value })}>
+                {this.filterList().map(processes =>
+                    this.renderProcessListItem(processes, isReadOnlyMode)
+                )}
+            </ListEditorView>
+        );
+    }
 
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Name')}</div>
-                                       <div className='name'>{name}</div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Artifact name')}</div>
-                                       <div className='artifact-name'>{artifactName}</div>
-                               </div>
-                               <div className='list-editor-item-view-field'>
-                                       <div className='title'>{i18n('Notes')}</div>
-                                       <div className='description'>{description}</div>
-                               </div>
-                       </ListEditorItemView>
-               );
-       }
+    renderProcessListItem(process, isReadOnlyMode) {
+        let { id, name, description, artifactName = '' } = process;
+        let {
+            currentSoftwareProduct: { version },
+            onEditProcess,
+            onDeleteProcess
+        } = this.props;
+        return (
+            <ListEditorItemView
+                key={id}
+                className="list-editor-item-view"
+                isReadOnlyMode={isReadOnlyMode}
+                onSelect={() => onEditProcess(process)}
+                onDelete={() => onDeleteProcess(process, version)}>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Name')}</div>
+                    <div className="name">{name}</div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Artifact name')}</div>
+                    <div className="artifact-name">{artifactName}</div>
+                </div>
+                <div className="list-editor-item-view-field">
+                    <div className="title">{i18n('Notes')}</div>
+                    <div className="description">{description}</div>
+                </div>
+            </ListEditorItemView>
+        );
+    }
 
-       filterList() {
-               let {processesList} = this.props;
-               let {localFilter} = this.state;
+    filterList() {
+        let { processesList } = this.props;
+        let { localFilter } = this.state;
 
-               if (localFilter.trim()) {
-                       const filter = new RegExp(escape(localFilter), 'i');
-                       return processesList.filter(({name = '', description = ''}) => {
-                               return escape(name).match(filter) || escape(description).match(filter);
-                       });
-               }
-               else {
-                       return processesList;
-               }
-       }
+        if (localFilter.trim()) {
+            const filter = new RegExp(escape(localFilter), 'i');
+            return processesList.filter(({ name = '', description = '' }) => {
+                return (
+                    escape(name).match(filter) ||
+                    escape(description).match(filter)
+                );
+            });
+        } else {
+            return processesList;
+        }
+    }
 }
 
 export default SoftwareProductProcessesListView;
index b0403ab..fb44530 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
 
 import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper.js';
 import SoftwareProductProcessesView from './SoftwareProductProcessesView.jsx';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductProcesses: {processesList, processesEditor}} = softwareProduct;
-       let {data} = processesEditor;
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductEditor: { data: currentSoftwareProduct = {} },
+        softwareProductProcesses: { processesList, processesEditor }
+    } = softwareProduct;
+    let { data } = processesEditor;
 
-       return {
-               currentSoftwareProduct,
-               processesList,
-               isDisplayEditor: Boolean(data),
-               isModalInEditMode: Boolean(data && data.id)
-       };
+    return {
+        currentSoftwareProduct,
+        processesList,
+        isDisplayEditor: Boolean(data),
+        isModalInEditMode: Boolean(data && data.id)
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onAddProcess: () => SoftwareProductProcessesActionHelper.openEditor(dispatch),
-               onEditProcess: (process) => SoftwareProductProcessesActionHelper.openEditor(dispatch, process),
-               onDeleteProcess: (process) => dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                       data:{
-                               msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}),
-                               confirmationButtonText: i18n('Delete'),
-                               title: i18n('Delete'),
-                               onConfirmed: ()=> SoftwareProductProcessesActionHelper.deleteProcess(dispatch,
-                                       {process, softwareProductId, version})
-                       }
-               })
-       };
+const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onAddProcess: () =>
+            SoftwareProductProcessesActionHelper.openEditor(dispatch),
+        onEditProcess: process =>
+            SoftwareProductProcessesActionHelper.openEditor(dispatch, process),
+        onDeleteProcess: process =>
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    msg: i18n('Are you sure you want to delete "{name}"?', {
+                        name: process.name
+                    }),
+                    confirmationButtonText: i18n('Delete'),
+                    title: i18n('Delete'),
+                    onConfirmed: () =>
+                        SoftwareProductProcessesActionHelper.deleteProcess(
+                            dispatch,
+                            {
+                                process,
+                                softwareProductId,
+                                version
+                            }
+                        )
+                }
+            })
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductProcessesView);
+export default connect(mapStateToProps, mapActionsToProps, null, {
+    withRef: true
+})(SoftwareProductProcessesView);
index 8fd370b..7c72c5b 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductProcessesConstants.js';
+import { actionTypes } from './SoftwareProductProcessesConstants.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 
 function baseUrl(vspId, version) {
-       let {id: versionId} = version;
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/processes`;
+    let { id: versionId } = version;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/processes`;
 }
 
 function putProcess(softwareProductId, version, process) {
-       return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${process.id}`, {
-               name: process.name,
-               description: process.description,
-               type: process.type === '' ? null : process.type
-       });
+    return RestAPIUtil.put(
+        `${baseUrl(softwareProductId, version)}/${process.id}`,
+        {
+            name: process.name,
+            description: process.description,
+            type: process.type === '' ? null : process.type
+        }
+    );
 }
 
 function postProcess(softwareProductId, version, process) {
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
-               name: process.name,
-               description: process.description,
-               type: process.type === '' ? null : process.type
-       });
+    return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
+        name: process.name,
+        description: process.description,
+        type: process.type === '' ? null : process.type
+    });
 }
 
 function deleteProcess(softwareProductId, version, processId) {
-       return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${processId}`);
+    return RestAPIUtil.destroy(
+        `${baseUrl(softwareProductId, version)}/${processId}`
+    );
 }
 
-function uploadFileToProcess(softwareProductId, version, processId, formData)
-{
-       return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}/${processId}/upload`, formData);
+function uploadFileToProcess(softwareProductId, version, processId, formData) {
+    return RestAPIUtil.post(
+        `${baseUrl(softwareProductId, version)}/${processId}/upload`,
+        formData
+    );
 }
 
 function fetchProcesses(softwareProductId, version) {
-       return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+    return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
 }
 
 const SoftwareProductActionHelper = {
-
-       fetchProcessesList(dispatch, {softwareProductId, version}) {
-
-               dispatch({
-                       type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES,
-                       processesList: []
-               });
-
-               return fetchProcesses(softwareProductId, version).then(response => {
-                       dispatch({
-                               type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES,
-                               processesList: response.results
-                       });
-               });
-       },
-       openEditor(dispatch, process = {}) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN,
-                       process
-               });
-       },
-
-       deleteProcess(dispatch, {process, softwareProductId, version}) {
-               return deleteProcess(softwareProductId, version, process.id).then(() => {
-                       dispatch({
-                               type: actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS,
-                               processId: process.id
-                       });
-               });
-
-       },
-
-       closeEditor(dispatch) {
-               dispatch({
-                       type:actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE
-               });
-       },
-
-       saveProcess(dispatch, {softwareProductId, version, previousProcess, process}) {
-               if (previousProcess) {
-                       return putProcess(softwareProductId, version, process).then(() => {
-                               if (process.formData){
-                                       uploadFileToProcess(softwareProductId, version, process.id, process.formData);
-                               }
-                               dispatch({
-                                       type: actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS,
-                                       process
-                               });
-                       });
-               }
-               else {
-                       return postProcess(softwareProductId, version, process).then(response => {
-                               if (process.formData) {
-                                       uploadFileToProcess(softwareProductId, version, response.value, process.formData);
-                               }
-                               dispatch({
-                                       type: actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS,
-                                       process: {
-                                               ...process,
-                                               id: response.value
-                                       }
-                               });
-                       });
-               }
-       },
-
-       hideDeleteConfirm(dispatch) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM,
-                       processToDelete: false
-               });
-       },
-
-       openDeleteProcessesConfirm(dispatch, {process} ) {
-               dispatch({
-                       type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM,
-                       processToDelete: process
-               });
-       }
-
+    fetchProcessesList(dispatch, { softwareProductId, version }) {
+        dispatch({
+            type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES,
+            processesList: []
+        });
+
+        return fetchProcesses(softwareProductId, version).then(response => {
+            dispatch({
+                type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES,
+                processesList: response.results
+            });
+        });
+    },
+    openEditor(dispatch, process = {}) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN,
+            process
+        });
+    },
+
+    deleteProcess(dispatch, { process, softwareProductId, version }) {
+        return deleteProcess(softwareProductId, version, process.id).then(
+            () => {
+                dispatch({
+                    type: actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS,
+                    processId: process.id
+                });
+            }
+        );
+    },
+
+    closeEditor(dispatch) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE
+        });
+    },
+
+    saveProcess(
+        dispatch,
+        { softwareProductId, version, previousProcess, process }
+    ) {
+        if (previousProcess) {
+            return putProcess(softwareProductId, version, process).then(() => {
+                if (process.formData) {
+                    uploadFileToProcess(
+                        softwareProductId,
+                        version,
+                        process.id,
+                        process.formData
+                    );
+                }
+                dispatch({
+                    type: actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS,
+                    process
+                });
+            });
+        } else {
+            return postProcess(softwareProductId, version, process).then(
+                response => {
+                    if (process.formData) {
+                        uploadFileToProcess(
+                            softwareProductId,
+                            version,
+                            response.value,
+                            process.formData
+                        );
+                    }
+                    dispatch({
+                        type: actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS,
+                        process: {
+                            ...process,
+                            id: response.value
+                        }
+                    });
+                }
+            );
+        }
+    },
+
+    hideDeleteConfirm(dispatch) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM,
+            processToDelete: false
+        });
+    },
+
+    openDeleteProcessesConfirm(dispatch, { process }) {
+        dispatch({
+            type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM,
+            processToDelete: process
+        });
+    }
 };
 
 export default SoftwareProductActionHelper;
-
index 6eee24c..7f09ea8 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       ADD_SOFTWARE_PRODUCT_PROCESS: null,
-       EDIT_SOFTWARE_PRODUCT_PROCESS: null,
-       DELETE_SOFTWARE_PRODUCT_PROCESS: null,
-       SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: null,
-       SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: null,
-       FETCH_SOFTWARE_PRODUCT_PROCESSES: null,
-       SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null
+    ADD_SOFTWARE_PRODUCT_PROCESS: null,
+    EDIT_SOFTWARE_PRODUCT_PROCESS: null,
+    DELETE_SOFTWARE_PRODUCT_PROCESS: null,
+    SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: null,
+    SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: null,
+    FETCH_SOFTWARE_PRODUCT_PROCESSES: null,
+    SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null
 });
 
 export const optionsInputValues = {
-       PROCESS_TYPE: [
-               {title: 'Select...', enum: ''},
-               {title: 'Other', enum: 'Other'}
-       ]
+    PROCESS_TYPE: [
+        { title: 'Select...', enum: '' },
+        { title: 'Other', enum: 'Other' }
+    ]
 };
 
 export const VSP_PROCESS_FORM = 'VSPPROCESSFORM';
index fc194fa..58cc894 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper';
 import SoftwareProductProcessesEditorView from './SoftwareProductProcessesEditorView.jsx';
-import {VSP_PROCESS_FORM} from './SoftwareProductProcessesConstants.js';
+import { VSP_PROCESS_FORM } from './SoftwareProductProcessesConstants.js';
 
-export const mapStateToProps = ({softwareProduct}) => {
-       let {softwareProductProcesses: {processesList, processesEditor}} = softwareProduct;
-       let {data, genericFieldInfo, formReady} = processesEditor;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-       let previousData;
-       const processId = data ? data.id : null;
-       if(processId) {
-               previousData = processesList.find(process => process.id === processId);
-       }
+export const mapStateToProps = ({ softwareProduct }) => {
+    let {
+        softwareProductProcesses: { processesList, processesEditor }
+    } = softwareProduct;
+    let { data, genericFieldInfo, formReady } = processesEditor;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+    let previousData;
+    const processId = data ? data.id : null;
+    if (processId) {
+        previousData = processesList.find(process => process.id === processId);
+    }
 
-       return {
-               data,
-               genericFieldInfo,
-               previousData,
-               isFormValid,
-               formReady
-       };
+    return {
+        data,
+        genericFieldInfo,
+        previousData,
+        isFormValid,
+        formReady
+    };
 };
 
-const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
-       return {
-               onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VSP_PROCESS_FORM}),
-               onSubmit: ({previousProcess, process}) => {
-                       SoftwareProductProcessesActionHelper.closeEditor(dispatch);
-                       SoftwareProductProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, process});
-               },
-               onCancel: () => SoftwareProductProcessesActionHelper.closeEditor(dispatch),
-               onValidateForm: () => ValidationHelper.validateForm(dispatch, VSP_PROCESS_FORM)
-       };
+const mapActionsToProps = (dispatch, { softwareProductId, version }) => {
+    return {
+        onDataChanged: deltaData =>
+            ValidationHelper.dataChanged(dispatch, {
+                deltaData,
+                formName: VSP_PROCESS_FORM
+            }),
+        onSubmit: ({ previousProcess, process }) => {
+            SoftwareProductProcessesActionHelper.closeEditor(dispatch);
+            SoftwareProductProcessesActionHelper.saveProcess(dispatch, {
+                softwareProductId,
+                version,
+                previousProcess,
+                process
+            });
+        },
+        onCancel: () =>
+            SoftwareProductProcessesActionHelper.closeEditor(dispatch),
+        onValidateForm: () =>
+            ValidationHelper.validateForm(dispatch, VSP_PROCESS_FORM)
+    };
 };
 
-export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductProcessesEditorView);
+export default connect(mapStateToProps, mapActionsToProps)(
+    SoftwareProductProcessesEditorView
+);
index d1bd602..6e8254f 100644 (file)
@@ -25,157 +25,212 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx';
 import GridItem from 'nfvo-components/grid/GridItem.jsx';
 
 const SoftwareProductProcessEditorPropType = PropTypes.shape({
-       id: PropTypes.string,
-       name: PropTypes.string,
-       description: PropTypes.string,
-       artifactName: PropTypes.string,
-       type: PropTypes.string
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    artifactName: PropTypes.string,
+    type: PropTypes.string
 });
 
-
-
 class SoftwareProductProcessesEditorForm extends React.Component {
+    static propTypes = {
+        data: SoftwareProductProcessEditorPropType,
+        previousData: SoftwareProductProcessEditorPropType,
+        isReadOnlyMode: PropTypes.bool,
+        onDataChanged: PropTypes.func,
+        onSubmit: PropTypes.func,
+        onCancel: PropTypes.func
+    };
+    state = {
+        dragging: false,
+        files: []
+    };
 
+    render() {
+        let {
+            data = {},
+            isReadOnlyMode,
+            onDataChanged,
+            onCancel,
+            genericFieldInfo,
+            optionsInputValues
+        } = this.props;
+        let { name, description, artifactName, type } = data;
 
-       static propTypes = {
-               data: SoftwareProductProcessEditorPropType,
-               previousData: SoftwareProductProcessEditorPropType,
-               isReadOnlyMode: PropTypes.bool,
-               onDataChanged: PropTypes.func,
-               onSubmit: PropTypes.func,
-               onCancel: PropTypes.func
-       };
-       state = {
-               dragging: false,
-               files: []
-       };
-
-       render() {
-               let {data = {}, isReadOnlyMode, onDataChanged, onCancel, genericFieldInfo, optionsInputValues} = this.props;
-               let {name, description, artifactName, type} = data;
-
-               return (
-                       <div>
-                               {genericFieldInfo && <Form
-                                       ref='validationForm'
-                                       hasButtons={true}
-                                       labledButtons={true}
-                                       isReadOnlyMode={isReadOnlyMode}
-                                       onSubmit={ () => this.submit() }
-                                       onReset={ () => onCancel() }
-                                       isValid={this.props.isFormValid}
-                                       formReady={this.props.formReady}
-                                       onValidateForm={() => this.props.onValidateForm() }
-                                       className='vsp-processes-editor'>
-                                       <div className={`vsp-processes-editor-data${isReadOnlyMode ? ' disabled' : '' }`}>
-                                               <Dropzone
-                                                       className={`vsp-process-dropzone-view ${this.state.dragging ? 'active-dragging' : ''}`}
-                                                       onDrop={(acceptedFiles, rejectedFiles) => this.handleImportSubmit(acceptedFiles, rejectedFiles)}
-                                                       onDragEnter={() => this.setState({dragging: true})}
-                                                       onDragLeave={() => this.setState({dragging: false})}
-                                                       multiple={false}
-                                                       disableClick={true}
-                                                       ref='processEditorFileInput'
-                                                       name='processEditorFileInput'>
-                                                       <GridSection hasLastColSet={true}>
-                                                               <GridItem colSpan={2}>
-                                                                       <Input
-                                                                               onChange={name => onDataChanged({name})}
-                                                                               isValid={genericFieldInfo.name.isValid}
-                                                                               isRequired={true}
-                                                                               data-test-id='name'
-                                                                               errorText={genericFieldInfo.name.errorText}
-                                                                               label={i18n('Name')}
-                                                                               value={name}
-                                                                               type='text'/>
-                                                               </GridItem>
-                                                               <GridItem colSpan={2} lastColInRow={true}>
-                                                                       <label>&nbsp;</label>
-                                                                       <DraggableUploadFileBox className='process-editor-file-box' isReadOnlyMode={isReadOnlyMode} onClick={() => this.refs.processEditorFileInput.open()}/>
-                                                               </GridItem>
-                                                       </GridSection>
-                                                       <GridSection hasLastColSet={true}>
-                                                               <GridItem colSpan={2}>
-                                                                       <Input
-                                                                               name='vsp-process-description'
-                                                                               groupClassName='vsp-process-description'
-                                                                               onChange={description => onDataChanged({description})}
-                                                                               isValid={genericFieldInfo.description.isValid}
-                                                                               errorText={genericFieldInfo.description.errorText}
-                                                                               label={i18n('Notes')}
-                                                                               value={description}
-                                                                               data-test-id='vsp-process-description'
-                                                                               type='textarea'/>
-                                                               </GridItem>
-                                                               <GridItem colSpan={2} lastColInRow={true}>
-                                                                       <Input
-                                                                               label={i18n('Artifacts')}
-                                                                               value={artifactName}
-                                                                               type='text'
-                                                                               disabled/>
-                                                                       <Input
-                                                                               onChange={e => {
-                                                                                       // setting the unit to the correct value
-                                                                                       const selectedIndex = e.target.selectedIndex;
-                                                                                       const val = e.target.options[selectedIndex].value;
-                                                                                       onDataChanged({type: val});}
-                                                                               }
-                                                                               value={type}
-                                                                               label={i18n('Process Type')}
-                                                                               className='process-type'
-                                                                               data-test-id='process-type'
-                                                                               isValid={genericFieldInfo.type.isValid}
-                                                                               errorText={genericFieldInfo.type.errorText}
-                                                                               type='select'>
-                                                                               {optionsInputValues.PROCESS_TYPE.map(mtype =>
-                                                                                       <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                                                                       </Input>
-                                                               </GridItem>
-                                                       </GridSection>
-                                               </Dropzone>
-                                       </div>
-                               </Form>}
-                       </div>
-               );
-       }
-
-       submit() {
-               const {data: process, previousData: previousProcess} = this.props;
-               let {files} = this.state;
-               let formData = false;
-               if (files.length) {
-                       let file = files[0];
-                       formData = new FormData();
-                       formData.append('upload', file);
-               }
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        labledButtons={true}
+                        isReadOnlyMode={isReadOnlyMode}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() => this.props.onValidateForm()}
+                        className="vsp-processes-editor">
+                        <div
+                            className={`vsp-processes-editor-data${
+                                isReadOnlyMode ? ' disabled' : ''
+                            }`}>
+                            <Dropzone
+                                className={`vsp-process-dropzone-view ${
+                                    this.state.dragging ? 'active-dragging' : ''
+                                }`}
+                                onDrop={(acceptedFiles, rejectedFiles) =>
+                                    this.handleImportSubmit(
+                                        acceptedFiles,
+                                        rejectedFiles
+                                    )
+                                }
+                                onDragEnter={() =>
+                                    this.setState({ dragging: true })
+                                }
+                                onDragLeave={() =>
+                                    this.setState({ dragging: false })
+                                }
+                                multiple={false}
+                                disableClick={true}
+                                ref="processEditorFileInput"
+                                name="processEditorFileInput">
+                                <GridSection hasLastColSet={true}>
+                                    <GridItem colSpan={2}>
+                                        <Input
+                                            onChange={name =>
+                                                onDataChanged({ name })
+                                            }
+                                            isValid={
+                                                genericFieldInfo.name.isValid
+                                            }
+                                            isRequired={true}
+                                            data-test-id="name"
+                                            errorText={
+                                                genericFieldInfo.name.errorText
+                                            }
+                                            label={i18n('Name')}
+                                            value={name}
+                                            type="text"
+                                        />
+                                    </GridItem>
+                                    <GridItem colSpan={2} lastColInRow={true}>
+                                        <label>&nbsp;</label>
+                                        <DraggableUploadFileBox
+                                            className="process-editor-file-box"
+                                            isReadOnlyMode={isReadOnlyMode}
+                                            onClick={() =>
+                                                this.refs.processEditorFileInput.open()
+                                            }
+                                        />
+                                    </GridItem>
+                                </GridSection>
+                                <GridSection hasLastColSet={true}>
+                                    <GridItem colSpan={2}>
+                                        <Input
+                                            name="vsp-process-description"
+                                            groupClassName="vsp-process-description"
+                                            onChange={description =>
+                                                onDataChanged({ description })
+                                            }
+                                            isValid={
+                                                genericFieldInfo.description
+                                                    .isValid
+                                            }
+                                            errorText={
+                                                genericFieldInfo.description
+                                                    .errorText
+                                            }
+                                            label={i18n('Notes')}
+                                            value={description}
+                                            data-test-id="vsp-process-description"
+                                            type="textarea"
+                                        />
+                                    </GridItem>
+                                    <GridItem colSpan={2} lastColInRow={true}>
+                                        <Input
+                                            label={i18n('Artifacts')}
+                                            value={artifactName}
+                                            type="text"
+                                            disabled
+                                        />
+                                        <Input
+                                            onChange={e => {
+                                                // setting the unit to the correct value
+                                                const selectedIndex =
+                                                    e.target.selectedIndex;
+                                                const val =
+                                                    e.target.options[
+                                                        selectedIndex
+                                                    ].value;
+                                                onDataChanged({ type: val });
+                                            }}
+                                            value={type}
+                                            label={i18n('Process Type')}
+                                            className="process-type"
+                                            data-test-id="process-type"
+                                            isValid={
+                                                genericFieldInfo.type.isValid
+                                            }
+                                            errorText={
+                                                genericFieldInfo.type.errorText
+                                            }
+                                            type="select">
+                                            {optionsInputValues.PROCESS_TYPE.map(
+                                                mtype => (
+                                                    <option
+                                                        key={mtype.enum}
+                                                        value={mtype.enum}>{`${
+                                                        mtype.title
+                                                    }`}</option>
+                                                )
+                                            )}
+                                        </Input>
+                                    </GridItem>
+                                </GridSection>
+                            </Dropzone>
+                        </div>
+                    </Form>
+                )}
+            </div>
+        );
+    }
 
-               let updatedProcess = {
-                       ...process,
-                       formData
-               };
-               this.props.onSubmit({process: updatedProcess, previousProcess});
-       }
+    submit() {
+        const { data: process, previousData: previousProcess } = this.props;
+        let { files } = this.state;
+        let formData = false;
+        if (files.length) {
+            let file = files[0];
+            formData = new FormData();
+            formData.append('upload', file);
+        }
 
+        let updatedProcess = {
+            ...process,
+            formData
+        };
+        this.props.onSubmit({ process: updatedProcess, previousProcess });
+    }
 
-       handleImportSubmit(files, rejectedFiles) {
-               if (files.length > 0) {
-                       let {onDataChanged} = this.props;
-                       this.setState({
-                               dragging: false,
-                               complete: '0',
-                               files
-                       });
-                       onDataChanged({artifactName: files[0].name});
-               }
-               else if (rejectedFiles.length > 0) {
-                       this.setState({
-                               dragging: false
-                       });
-                       if (DEBUG) {
-                               console.log('file was rejected.' + rejectedFiles[0].name);
-                       }
-               }
-       }
+    handleImportSubmit(files, rejectedFiles) {
+        if (files.length > 0) {
+            let { onDataChanged } = this.props;
+            this.setState({
+                dragging: false,
+                complete: '0',
+                files
+            });
+            onDataChanged({ artifactName: files[0].name });
+        } else if (rejectedFiles.length > 0) {
+            this.setState({
+                dragging: false
+            });
+            if (DEBUG) {
+                console.log('file was rejected.' + rejectedFiles[0].name);
+            }
+        }
+    }
 }
 
 export default SoftwareProductProcessesEditorForm;
index 11b89b1..a8731fd 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes, VSP_PROCESS_FORM} from './SoftwareProductProcessesConstants.js';
+import {
+    actionTypes,
+    VSP_PROCESS_FORM
+} from './SoftwareProductProcessesConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN:
-                       return {
-                               ...state,
-                               formReady: null,
-                               formName: VSP_PROCESS_FORM,
-                               genericFieldInfo: {
-                                       'name' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
-                                       },
-                                       'description' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: [{type: 'maxLength', data: 1000}]
-                                       },
-                                       'artifactName' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       },
-                                       'type' : {
-                                               isValid: true,
-                                               errorText: '',
-                                               validations: []
-                                       }
-                               },
-                               data: action.process
-                       };
-               case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE:
-                       return {};
+    switch (action.type) {
+        case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN:
+            return {
+                ...state,
+                formReady: null,
+                formName: VSP_PROCESS_FORM,
+                genericFieldInfo: {
+                    name: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [
+                            { type: 'required', data: true },
+                            { type: 'maxLength', data: 120 }
+                        ]
+                    },
+                    description: {
+                        isValid: true,
+                        errorText: '',
+                        validations: [{ type: 'maxLength', data: 1000 }]
+                    },
+                    artifactName: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    },
+                    type: {
+                        isValid: true,
+                        errorText: '',
+                        validations: []
+                    }
+                },
+                data: action.process
+            };
+        case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE:
+            return {};
 
-               default:
-                       return state;
-       }
+        default:
+            return state;
+    }
 };
index 9ce690a..867090b 100644 (file)
  */
 import React from 'react';
 
-import  {optionsInputValues as ProcessesOptionsInputValues} from './SoftwareProductProcessesConstants.js';
+import { optionsInputValues as ProcessesOptionsInputValues } from './SoftwareProductProcessesConstants.js';
 import SoftwareProductProcessesEditorForm from './SoftwareProductProcessesEditorForm.jsx';
 
-
 class SoftwareProductProcessesEditorView extends React.Component {
-       render() {
-               return (
-                       <SoftwareProductProcessesEditorForm optionsInputValues={ProcessesOptionsInputValues} {...this.props}/>
-               );
-       }
+    render() {
+        return (
+            <SoftwareProductProcessesEditorForm
+                optionsInputValues={ProcessesOptionsInputValues}
+                {...this.props}
+            />
+        );
+    }
 }
 
 export default SoftwareProductProcessesEditorView;
index 20390d1..0e4d946 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {actionTypes} from './SoftwareProductProcessesConstants.js';
+import { actionTypes } from './SoftwareProductProcessesConstants.js';
 
 export default (state = [], action) => {
-       switch (action.type) {
-               case actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES:
-                       return [...action.processesList];
-               case actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS:
-                       const indexForEdit = state.findIndex(process => process.id === action.process.id);
-                       return [...state.slice(0, indexForEdit), action.process, ...state.slice(indexForEdit + 1)];
-               case actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS:
-                       return [...state, action.process];
-               case actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS:
-                       return state.filter(process => process.id !== action.processId);
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES:
+            return [...action.processesList];
+        case actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS:
+            const indexForEdit = state.findIndex(
+                process => process.id === action.process.id
+            );
+            return [
+                ...state.slice(0, indexForEdit),
+                action.process,
+                ...state.slice(indexForEdit + 1)
+            ];
+        case actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS:
+            return [...state, action.process];
+        case actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS:
+            return state.filter(process => process.id !== action.processId);
+        default:
+            return state;
+    }
 };
index b0da767..1357c31 100644 (file)
@@ -20,45 +20,63 @@ import Modal from 'nfvo-components/modal/Modal.jsx';
 import SoftwareProductProcessesEditor from './SoftwareProductProcessesEditor.js';
 import SoftwareProductProcessListView from './SoftwareProductProcessListView.jsx';
 
-
 class SoftwareProductProcessesView extends React.Component {
+    state = {
+        localFilter: ''
+    };
 
-       state = {
-               localFilter: ''
-       };
-
-       static propTypes = {
-               onAddProcess: PropTypes.func.isRequired,
-               onEditProcess: PropTypes.func.isRequired,
-               onDeleteProcess: PropTypes.func.isRequired,
-               isDisplayEditor: PropTypes.bool.isRequired,
-               isReadOnlyMode: PropTypes.bool.isRequired,
-               currentSoftwareProduct:PropTypes.object
-       };
-
-       render() {
-               return (
-                       <div className='software-product-landing-view-right-side vsp-processes-page'>
-                               {this.renderEditor()}
-                               <SoftwareProductProcessListView addButtonTitle={i18n('Add Process Details')} {...this.props}/>
-                       </div>
-               );
-       }
+    static propTypes = {
+        onAddProcess: PropTypes.func.isRequired,
+        onEditProcess: PropTypes.func.isRequired,
+        onDeleteProcess: PropTypes.func.isRequired,
+        isDisplayEditor: PropTypes.bool.isRequired,
+        isReadOnlyMode: PropTypes.bool.isRequired,
+        currentSoftwareProduct: PropTypes.object
+    };
 
-       renderEditor() {
-               let {currentSoftwareProduct: {id}, version, isModalInEditMode, isReadOnlyMode, isDisplayEditor} = this.props;
-               return (
+    render() {
+        return (
+            <div className="software-product-landing-view-right-side vsp-processes-page">
+                {this.renderEditor()}
+                <SoftwareProductProcessListView
+                    addButtonTitle={i18n('Add Process Details')}
+                    {...this.props}
+                />
+            </div>
+        );
+    }
 
-                       <Modal show={isDisplayEditor} bsSize='large' animation={true} className='onborading-modal'>
-                               <Modal.Header>
-                                       <Modal.Title>{isModalInEditMode ? i18n('Edit Process Details') : i18n('Create New Process Details')}</Modal.Title>
-                               </Modal.Header>
-                               <Modal.Body className='edit-process-modal'>
-                                       <SoftwareProductProcessesEditor softwareProductId={id} version={version} isReadOnlyMode={isReadOnlyMode}/>
-                               </Modal.Body>
-                       </Modal>
-               );
-       }
+    renderEditor() {
+        let {
+            currentSoftwareProduct: { id },
+            version,
+            isModalInEditMode,
+            isReadOnlyMode,
+            isDisplayEditor
+        } = this.props;
+        return (
+            <Modal
+                show={isDisplayEditor}
+                bsSize="large"
+                animation={true}
+                className="onborading-modal">
+                <Modal.Header>
+                    <Modal.Title>
+                        {isModalInEditMode
+                            ? i18n('Edit Process Details')
+                            : i18n('Create New Process Details')}
+                    </Modal.Title>
+                </Modal.Header>
+                <Modal.Body className="edit-process-modal">
+                    <SoftwareProductProcessesEditor
+                        softwareProductId={id}
+                        version={version}
+                        isReadOnlyMode={isReadOnlyMode}
+                    />
+                </Modal.Body>
+            </Modal>
+        );
+    }
 }
 
 export default SoftwareProductProcessesView;
index 2c3442e..a300499 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes} from './UserNotificationsConstants.js';
+import { actionTypes } from './UserNotificationsConstants.js';
 
 export default (state = {}, action) => {
-       switch (action.type) {
-               case actionTypes.NOTIFICATION:
-                       let list = (state.notificationsList) ? state.notificationsList : [];
-                       const {notifications, lastScanned} = action.data;
-                       return {
-                               ...state,
-                               lastScanned,
-                               notificationsList: [...notifications, ...list],
-                               numOfNotSeenNotifications: state.numOfNotSeenNotifications + notifications.length
-                       };
-               case actionTypes.LOAD_NOTIFICATIONS:
-                       return {
-                               ...state,
-                               ...action.result,
-                               notificationsList: action.result.notifications,
-                               notifications: undefined
-                       };
-               case actionTypes.LOAD_PREV_NOTIFICATIONS:
-                       const {notifications: prevNotifications, endOfPage: newEndOfPage} = action.result;
-                       return {
-                               ...state,
-                               notificationsList: [
-                                       ...state.notificationsList,
-                                       ...prevNotifications
-                               ],
-                               endOfPage: newEndOfPage
-                       };
-               case actionTypes.UPDATE_READ_NOTIFICATION:
-                       let {notificationForUpdate} = action;
-                       notificationForUpdate = {...notificationForUpdate, read: true};
-                       const indexForEdit = state.notificationsList.findIndex(notification => notification.eventId === notificationForUpdate.eventId);
-                       return {
-                               ...state,
-                               notificationsList: [
-                                       ...state.notificationsList.slice(0, indexForEdit),
-                                       notificationForUpdate,
-                                       ...state.notificationsList.slice(indexForEdit + 1)
-                               ]
-                       };
-               case actionTypes.RESET_NEW_NOTIFICATIONS:
-                       return {
-                               ...state,
-                               numOfNotSeenNotifications: 0
-                       };
-               case actionTypes.TOGGLE_OVERLAY:
-                       return {
-                               ...state,
-                               showNotificationsOverlay: action.showNotificationsOverlay
-                       };
-               default:
-                       return state;
-       }
+    switch (action.type) {
+        case actionTypes.NOTIFICATION:
+            let list = state.notificationsList ? state.notificationsList : [];
+            const { notifications, lastScanned } = action.data;
+            return {
+                ...state,
+                lastScanned,
+                notificationsList: [...notifications, ...list],
+                numOfNotSeenNotifications:
+                    state.numOfNotSeenNotifications + notifications.length
+            };
+        case actionTypes.LOAD_NOTIFICATIONS:
+            return {
+                ...state,
+                ...action.result,
+                notificationsList: action.result.notifications,
+                notifications: undefined
+            };
+        case actionTypes.LOAD_PREV_NOTIFICATIONS:
+            const {
+                notifications: prevNotifications,
+                endOfPage: newEndOfPage
+            } = action.result;
+            return {
+                ...state,
+                notificationsList: [
+                    ...state.notificationsList,
+                    ...prevNotifications
+                ],
+                endOfPage: newEndOfPage
+            };
+        case actionTypes.UPDATE_READ_NOTIFICATION:
+            let { notificationForUpdate } = action;
+            notificationForUpdate = { ...notificationForUpdate, read: true };
+            const indexForEdit = state.notificationsList.findIndex(
+                notification =>
+                    notification.eventId === notificationForUpdate.eventId
+            );
+            return {
+                ...state,
+                notificationsList: [
+                    ...state.notificationsList.slice(0, indexForEdit),
+                    notificationForUpdate,
+                    ...state.notificationsList.slice(indexForEdit + 1)
+                ]
+            };
+        case actionTypes.RESET_NEW_NOTIFICATIONS:
+            return {
+                ...state,
+                numOfNotSeenNotifications: 0
+            };
+        case actionTypes.TOGGLE_OVERLAY:
+            return {
+                ...state,
+                showNotificationsOverlay: action.showNotificationsOverlay
+            };
+        default:
+            return state;
+    }
 };
index de105d2..7f5b334 100644 (file)
@@ -18,89 +18,155 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import enhanceWithClickOutside from 'react-click-outside';
 import classnames from 'classnames';
-import {connect} from 'react-redux';
+import { connect } from 'react-redux';
 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
 import Overlay from 'nfvo-components/overlay/Overlay.jsx';
 import UserNotifications from 'sdc-app/onboarding/userNotifications/UserNotifications.jsx';
 import UserNotificationsActionHelper from 'sdc-app/onboarding/userNotifications/UserNotificationsActionHelper.js';
-import {actionTypes} from './UserNotificationsConstants.js';
+import { actionTypes } from './UserNotificationsConstants.js';
 import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
 
-const mapStateToProps = ({currentScreen, notifications, users: {usersList}}) => {
-       return {currentScreen, notifications, usersList};
+const mapStateToProps = ({
+    currentScreen,
+    notifications,
+    users: { usersList }
+}) => {
+    return { currentScreen, notifications, usersList };
 };
 
-const mapActionToProps = (dispatch) => {
-       return {
-               resetNewNotifications: notificationId => UserNotificationsActionHelper.updateLastSeenNotification(dispatch, {notificationId}),
-               toggleOverlay: ({showNotificationsOverlay}) => dispatch({type: actionTypes.TOGGLE_OVERLAY, showNotificationsOverlay}),
-               onLoadPrevNotifications: (lastScanned, endOfPage) => UserNotificationsActionHelper.loadPreviousNotifications(dispatch, {lastScanned, endOfPage}),
-               onSync: ({itemId, itemName, versionId, versionName, currentScreen}) =>  UserNotificationsActionHelper.syncItem(dispatch, {itemId, itemName, versionId, versionName, currentScreen}),
-               updateNotification: notificationForUpdate => UserNotificationsActionHelper.updateNotification(dispatch, {notificationForUpdate}),
-               onLoadItemsLists: () => OnboardingActionHelper.loadItemsLists(dispatch)
-       };
+const mapActionToProps = dispatch => {
+    return {
+        resetNewNotifications: notificationId =>
+            UserNotificationsActionHelper.updateLastSeenNotification(dispatch, {
+                notificationId
+            }),
+        toggleOverlay: ({ showNotificationsOverlay }) =>
+            dispatch({
+                type: actionTypes.TOGGLE_OVERLAY,
+                showNotificationsOverlay
+            }),
+        onLoadPrevNotifications: (lastScanned, endOfPage) =>
+            UserNotificationsActionHelper.loadPreviousNotifications(dispatch, {
+                lastScanned,
+                endOfPage
+            }),
+        onSync: ({ itemId, itemName, versionId, versionName, currentScreen }) =>
+            UserNotificationsActionHelper.syncItem(dispatch, {
+                itemId,
+                itemName,
+                versionId,
+                versionName,
+                currentScreen
+            }),
+        updateNotification: notificationForUpdate =>
+            UserNotificationsActionHelper.updateNotification(dispatch, {
+                notificationForUpdate
+            }),
+        onLoadItemsLists: () => OnboardingActionHelper.loadItemsLists(dispatch)
+    };
 };
 
-
 class NotificationsView extends React.Component {
+    static propTypes = {
+        currentScreen: PropTypes.object,
+        notifications: PropTypes.object,
+        resetNewNotifications: PropTypes.func,
+        toggleOverlay: PropTypes.func,
+        onLoadPrevNotifications: PropTypes.func,
+        onSync: PropTypes.func,
+        updateNotification: PropTypes.func,
+        onLoadItemsLists: PropTypes.func
+    };
 
-       static propTypes = {
-               currentScreen: PropTypes.object,
-               notifications: PropTypes.object,
-               resetNewNotifications: PropTypes.func,
-               toggleOverlay: PropTypes.func,
-               onLoadPrevNotifications: PropTypes.func,
-               onSync: PropTypes.func,
-               updateNotification: PropTypes.func,
-               onLoadItemsLists: PropTypes.func
-       };
-
-       render() {
-               const {usersList, notifications, onLoadPrevNotifications, onSync, updateNotification, onLoadItemsLists, currentScreen} = this.props;
-               const {notificationsList, numOfNotSeenNotifications, showNotificationsOverlay, lastScanned, endOfPage} = notifications;
+    render() {
+        const {
+            usersList,
+            notifications,
+            onLoadPrevNotifications,
+            onSync,
+            updateNotification,
+            onLoadItemsLists,
+            currentScreen
+        } = this.props;
+        const {
+            notificationsList,
+            numOfNotSeenNotifications,
+            showNotificationsOverlay,
+            lastScanned,
+            endOfPage
+        } = notifications;
 
-               return (
-                       <div className='onboarding-notifications'>
-                               <div className='notifications-icon' onClick={() => this.onNotificationIconClick()}>
-                                       <SVGIcon name={numOfNotSeenNotifications > 0 ? 'notificationFullBell' : 'notificationBell'} color={numOfNotSeenNotifications > 0 ? 'primary' : ''}/>
-                                       <div className={classnames('notifications-count', {'hidden-count': numOfNotSeenNotifications === 0})}>
-                                                       {numOfNotSeenNotifications}
-                                       </div>
-                               </div>
-                               {showNotificationsOverlay &&
-                                       <Overlay>
-                                               <UserNotifications notificationsList={notificationsList} usersList={usersList} lastScanned={lastScanned} endOfPage={endOfPage}
-                                                       onLoadPrevNotifications={onLoadPrevNotifications} onSync={onSync} updateNotification={updateNotification} onLoadItemsLists={onLoadItemsLists}
-                                                       currentScreen={currentScreen}/>
-                                       </Overlay>
-                               }
-                       </div>
-               );
-       }
+        return (
+            <div className="onboarding-notifications">
+                <div
+                    className="notifications-icon"
+                    onClick={() => this.onNotificationIconClick()}>
+                    <SVGIcon
+                        name={
+                            numOfNotSeenNotifications > 0
+                                ? 'notificationFullBell'
+                                : 'notificationBell'
+                        }
+                        color={numOfNotSeenNotifications > 0 ? 'primary' : ''}
+                    />
+                    <div
+                        className={classnames('notifications-count', {
+                            'hidden-count': numOfNotSeenNotifications === 0
+                        })}>
+                        {numOfNotSeenNotifications}
+                    </div>
+                </div>
+                {showNotificationsOverlay && (
+                    <Overlay>
+                        <UserNotifications
+                            notificationsList={notificationsList}
+                            usersList={usersList}
+                            lastScanned={lastScanned}
+                            endOfPage={endOfPage}
+                            onLoadPrevNotifications={onLoadPrevNotifications}
+                            onSync={onSync}
+                            updateNotification={updateNotification}
+                            onLoadItemsLists={onLoadItemsLists}
+                            currentScreen={currentScreen}
+                        />
+                    </Overlay>
+                )}
+            </div>
+        );
+    }
 
-       handleClickOutside() {
-               const {notifications: {showNotificationsOverlay}} = this.props;
-               if(showNotificationsOverlay) {
-                       this.onCloseOverlay();
-               }
-       }
+    handleClickOutside() {
+        const { notifications: { showNotificationsOverlay } } = this.props;
+        if (showNotificationsOverlay) {
+            this.onCloseOverlay();
+        }
+    }
 
-       onNotificationIconClick() {
-               const {notifications: {showNotificationsOverlay}, toggleOverlay} = this.props;
-               if (showNotificationsOverlay) {
-                       this.onCloseOverlay();
-               } else {
-                       toggleOverlay({showNotificationsOverlay: true});
-               }
-       }
+    onNotificationIconClick() {
+        const {
+            notifications: { showNotificationsOverlay },
+            toggleOverlay
+        } = this.props;
+        if (showNotificationsOverlay) {
+            this.onCloseOverlay();
+        } else {
+            toggleOverlay({ showNotificationsOverlay: true });
+        }
+    }
 
-       onCloseOverlay() {
-               const {notifications: {numOfNotSeenNotifications, lastScanned}, resetNewNotifications, toggleOverlay} = this.props;
-               if (numOfNotSeenNotifications) {
-                       resetNewNotifications(lastScanned);
-               }
-               toggleOverlay({showNotificationsOverlay: false});
-       }
+    onCloseOverlay() {
+        const {
+            notifications: { numOfNotSeenNotifications, lastScanned },
+            resetNewNotifications,
+            toggleOverlay
+        } = this.props;
+        if (numOfNotSeenNotifications) {
+            resetNewNotifications(lastScanned);
+        }
+        toggleOverlay({ showNotificationsOverlay: false });
+    }
 }
 
-export default connect(mapStateToProps, mapActionToProps)(enhanceWithClickOutside(NotificationsView));
+export default connect(mapStateToProps, mapActionToProps)(
+    enhanceWithClickOutside(NotificationsView)
+);
index fd5c04d..01ca50c 100644 (file)
@@ -19,126 +19,193 @@ import PropTypes from 'prop-types';
 import ReactDOM from 'react-dom';
 import classnames from 'classnames';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-import {notificationType} from './UserNotificationsConstants.js';
+import { notificationType } from './UserNotificationsConstants.js';
 import ShowMore from 'react-show-more';
 
-const Notification = ({notification, users, onActionClicked, getNotificationTypeDesc}) => {
-       const {eventType, read, eventAttributes, dateTime} = notification;
-       const {itemName, userId, description, versionName, permission, granted} = eventAttributes;
-       const {fullName: userName} = users.find(user => user.userId === userId);
-       return (
-               <div className={classnames('notification', {'unread': !read})}>
-                       <div className='notification-data'>
-                               <div className='item-name'>
-                                       {itemName}
-                                       {versionName && <span>&nbsp;&nbsp;&nbsp;v{versionName}</span>}
-                                       {!read && <div className='unread-circle-icon'></div> }
-                               </div>
-                               <div className='flex-items'>
-                                       <div className='type'>{getNotificationTypeDesc(eventType, permission, granted)}</div>
-                                       <div className='separator'/>
-                                       <div className='user-name'>{`${i18n('By')} ${userName}`}</div>
-                               </div>
-                               {(description || versionName) && <div className='description'>
-                                       {description && <ShowMore anchorClass='more-less' lines={2} more={i18n('More')} less={i18n('Less')}>
-                                               {description}
-                                       </ShowMore>}
-                                       {eventType === notificationType.ITEM_CHANGED.SUBMIT &&
-                                               <div>
-                                                       <div>{i18n('Version {versionName} was submitted.', {versionName: versionName})}</div>
-                                               </div>
-                                       }
-                               </div>
-                               }
-                               <div className='date'>{dateTime}</div>
-                       </div>
-                       <div className='notification-action'>
-                               <div className={classnames('action-button', {'hidden': read})} onClick={() => onActionClicked(notification)}>
-                                       {eventType === notificationType.PERMISSION_CHANGED
-                                               || eventType === notificationType.ITEM_DELETED
-                                               || eventType === notificationType.ITEM_ARCHIVED
-                                               || eventType === notificationType.ITEM_RESTORED ? i18n('OK') : i18n('Sync')}
-                               </div>
-                       </div>
-               </div>
-       );
+const Notification = ({
+    notification,
+    users,
+    onActionClicked,
+    getNotificationTypeDesc
+}) => {
+    const { eventType, read, eventAttributes, dateTime } = notification;
+    const {
+        itemName,
+        userId,
+        description,
+        versionName,
+        permission,
+        granted
+    } = eventAttributes;
+    const { fullName: userName } = users.find(user => user.userId === userId);
+    return (
+        <div className={classnames('notification', { unread: !read })}>
+            <div className="notification-data">
+                <div className="item-name">
+                    {itemName}
+                    {versionName && (
+                        <span>&nbsp;&nbsp;&nbsp;v{versionName}</span>
+                    )}
+                    {!read && <div className="unread-circle-icon" />}
+                </div>
+                <div className="flex-items">
+                    <div className="type">
+                        {getNotificationTypeDesc(
+                            eventType,
+                            permission,
+                            granted
+                        )}
+                    </div>
+                    <div className="separator" />
+                    <div className="user-name">{`${i18n(
+                        'By'
+                    )} ${userName}`}</div>
+                </div>
+                {(description || versionName) && (
+                    <div className="description">
+                        {description && (
+                            <ShowMore
+                                anchorClass="more-less"
+                                lines={2}
+                                more={i18n('More')}
+                                less={i18n('Less')}>
+                                {description}
+                            </ShowMore>
+                        )}
+                        {eventType === notificationType.ITEM_CHANGED.SUBMIT && (
+                            <div>
+                                <div>
+                                    {i18n(
+                                        'Version {versionName} was submitted.',
+                                        { versionName: versionName }
+                                    )}
+                                </div>
+                            </div>
+                        )}
+                    </div>
+                )}
+                <div className="date">{dateTime}</div>
+            </div>
+            <div className="notification-action">
+                <div
+                    className={classnames('action-button', { hidden: read })}
+                    onClick={() => onActionClicked(notification)}>
+                    {eventType === notificationType.PERMISSION_CHANGED ||
+                    eventType === notificationType.ITEM_DELETED ||
+                    eventType === notificationType.ITEM_ARCHIVED ||
+                    eventType === notificationType.ITEM_RESTORED
+                        ? i18n('OK')
+                        : i18n('Sync')}
+                </div>
+            </div>
+        </div>
+    );
 };
 
 function getNotificationTypeDesc(eventType, permission, granted) {
-       switch (eventType) {
-               case notificationType.PERMISSION_CHANGED:
-                       const grantedStr = granted ? i18n('Granted') : i18n('Taken');
-                       return `${i18n('Permission')} ${grantedStr}: ${permission}`;                    
-               case notificationType.ITEM_CHANGED.COMMIT:
-                       return i18n('Your Copy Is Out Of Sync');
-               case notificationType.ITEM_CHANGED.SUBMIT:
-                       return i18n('Version Submitted');
-               case notificationType.ITEM_DELETED:
-                       return i18n('Item was deleted');
-               case notificationType.ITEM_ARCHIVED:
-                       return i18n('Item was archived');
-               case notificationType.ITEM_RESTORED:
-                       return i18n('Item was restored from archive');
-       }
+    switch (eventType) {
+        case notificationType.PERMISSION_CHANGED:
+            const grantedStr = granted ? i18n('Granted') : i18n('Taken');
+            return `${i18n('Permission')} ${grantedStr}: ${permission}`;
+        case notificationType.ITEM_CHANGED.COMMIT:
+            return i18n('Your Copy Is Out Of Sync');
+        case notificationType.ITEM_CHANGED.SUBMIT:
+            return i18n('Version Submitted');
+        case notificationType.ITEM_DELETED:
+            return i18n('Item was deleted');
+        case notificationType.ITEM_ARCHIVED:
+            return i18n('Item was archived');
+        case notificationType.ITEM_RESTORED:
+            return i18n('Item was restored from archive');
+    }
 }
 
 class UserNotifications extends React.Component {
+    static propTypes = {
+        currentScreen: PropTypes.object,
+        notificationsList: PropTypes.array,
+        usersList: PropTypes.array,
+        lastScanned: PropTypes.string,
+        endOfPage: PropTypes.string,
+        onLoadPrevNotifications: PropTypes.func,
+        onSync: PropTypes.func,
+        updateNotification: PropTypes.func,
+        onLoadItemsLists: PropTypes.func
+    };
 
-       static propTypes = {
-               currentScreen: PropTypes.object,
-               notificationsList: PropTypes.array,
-               usersList: PropTypes.array,
-               lastScanned: PropTypes.string,
-               endOfPage:PropTypes.string,
-               onLoadPrevNotifications: PropTypes.func,
-               onSync: PropTypes.func,
-               updateNotification: PropTypes.func,
-               onLoadItemsLists: PropTypes.func
-       };
+    render() {
+        const {
+            notificationsList = [],
+            usersList,
+            lastScanned,
+            endOfPage
+        } = this.props;
 
-       render() {
-               const {notificationsList = [], usersList, lastScanned, endOfPage} = this.props;
+        return (
+            <div className="user-notifications">
+                <div className="notifications-title">
+                    {i18n('Notifications')}
+                </div>
+                <div
+                    className="notifications-list"
+                    ref="notificationList"
+                    onScroll={() =>
+                        this.loadPrevNotifications(lastScanned, endOfPage)
+                    }>
+                    {notificationsList.map(notification => (
+                        <Notification
+                            key={notification.eventId}
+                            notification={notification}
+                            users={usersList}
+                            onActionClicked={notification =>
+                                this.onActionClicked(notification)
+                            }
+                            getNotificationTypeDesc={getNotificationTypeDesc}
+                        />
+                    ))}
+                </div>
+            </div>
+        );
+    }
 
-               return (
-                       <div className='user-notifications'>
-                               <div className='notifications-title'>{i18n('Notifications')}</div>
-                               <div className='notifications-list' ref='notificationList' onScroll={() => this.loadPrevNotifications(lastScanned, endOfPage)}>
-                               {
-                                       notificationsList.map(notification => (
-                                               <Notification key={notification.eventId} notification={notification} users={usersList}
-                                                       onActionClicked={notification => this.onActionClicked(notification)}
-                                                       getNotificationTypeDesc={getNotificationTypeDesc}/>))
-                               }
-                               </div>
-                       </div>
-               );
-       }
+    onActionClicked(notification) {
+        const {
+            onSync,
+            updateNotification,
+            currentScreen,
+            onLoadItemsLists
+        } = this.props;
+        const {
+            eventType,
+            eventAttributes: { itemId, itemName, versionId, versionName }
+        } = notification;
+        if (
+            eventType !== notificationType.PERMISSION_CHANGED &&
+            eventType !== notificationType.ITEM_DELETED &&
+            eventType !== notificationType.ITEM_ARCHIVED &&
+            eventType !== notificationType.ITEM_RESTORED
+        ) {
+            onSync({ itemId, itemName, versionId, versionName, currentScreen });
+        } else {
+            onLoadItemsLists();
+        }
+        updateNotification(notification);
+    }
 
-       onActionClicked(notification) {
-               const {onSync, updateNotification, currentScreen, onLoadItemsLists} = this.props;
-               const {eventType, eventAttributes: {itemId, itemName, versionId, versionName}} = notification;          
-               if(eventType !== notificationType.PERMISSION_CHANGED &&
-                       eventType !== notificationType.ITEM_DELETED &&
-                       eventType !== notificationType.ITEM_ARCHIVED &&
-                       eventType !== notificationType.ITEM_RESTORED) {
-                       onSync({itemId, itemName, versionId, versionName, currentScreen});
-               }
-               else {
-                       onLoadItemsLists();
-               }
-               updateNotification(notification);
-       }
+    loadPrevNotifications(lastScanned, endOfPage) {
+        if (endOfPage && lastScanned) {
+            let element = ReactDOM.findDOMNode(this.refs['notificationList']);
+            const { onLoadPrevNotifications } = this.props;
 
-       loadPrevNotifications(lastScanned, endOfPage) {
-               if(endOfPage && lastScanned) {
-                       let element = ReactDOM.findDOMNode(this.refs['notificationList']);
-                       const {onLoadPrevNotifications} = this.props;
-
-                       if (element && element.clientHeight + element.scrollTop === element.scrollHeight) {
-                               onLoadPrevNotifications(lastScanned, endOfPage);
-                       }
-               }
-       }
+            if (
+                element &&
+                element.clientHeight + element.scrollTop ===
+                    element.scrollHeight
+            ) {
+                onLoadPrevNotifications(lastScanned, endOfPage);
+            }
+        }
+    }
 }
 
-export default UserNotifications;
\ No newline at end of file
+export default UserNotifications;
index 574aa0f..f8693e1 100644 (file)
-import {actionTypes} from './UserNotificationsConstants.js';
+import { actionTypes } from './UserNotificationsConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
-import WebSocketUtil, {websocketUrl} from 'nfvo-utils/WebSocketUtil.js';
-import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import WebSocketUtil, { websocketUrl } from 'nfvo-utils/WebSocketUtil.js';
+import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-import {SyncStates} from 'sdc-app/common/merge/MergeEditorConstants.js';
+import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
+import { SyncStates } from 'sdc-app/common/merge/MergeEditorConstants.js';
 
 function baseUrl() {
-       const restPrefix = Configuration.get('restPrefix');
-       return `${restPrefix}/v1.0/notifications`;
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/notifications`;
 }
 
 function fetch() {
-       return RestAPIUtil.fetch(baseUrl());
+    return RestAPIUtil.fetch(baseUrl());
 }
 
 function updateNotification(notificationId) {
-       return RestAPIUtil.put(`${baseUrl()}/${notificationId}`);
+    return RestAPIUtil.put(`${baseUrl()}/${notificationId}`);
 }
 
 function updateLastSeenNotification(notificationId) {
-       return RestAPIUtil.put(`${baseUrl()}/last-seen/${notificationId}`);
+    return RestAPIUtil.put(`${baseUrl()}/last-seen/${notificationId}`);
 }
 
 function loadPrevNotifications(lastScanned, endOfPage) {
-       return RestAPIUtil.fetch(`${baseUrl()}?LAST_DELIVERED_EVENT_ID=${lastScanned}&END_OF_PAGE_EVENT_ID=${endOfPage}`);
+    return RestAPIUtil.fetch(
+        `${baseUrl()}?LAST_DELIVERED_EVENT_ID=${lastScanned}&END_OF_PAGE_EVENT_ID=${endOfPage}`
+    );
 }
 
 const INITIAL_LAST_SCANNED = '00000000-0000-1000-8080-808080808080';
 
 const UserNotificationsActionHelper = {
-       notificationsFirstHandling(dispatch) {
-               console.log('Websocket Url: ', websocketUrl);
-               UserNotificationsActionHelper.fetchUserNotificationsList(dispatch).then(({lastScanned}) => {
-                       WebSocketUtil.open(websocketUrl, {lastScanned: lastScanned || INITIAL_LAST_SCANNED});
-               });
-       },
+    notificationsFirstHandling(dispatch) {
+        console.log('Websocket Url: ', websocketUrl);
+        UserNotificationsActionHelper.fetchUserNotificationsList(dispatch).then(
+            ({ lastScanned }) => {
+                WebSocketUtil.open(websocketUrl, {
+                    lastScanned: lastScanned || INITIAL_LAST_SCANNED
+                });
+            }
+        );
+    },
 
-       fetchUserNotificationsList(dispatch) {
-               return fetch().then(result => {
-                       dispatch({
-                               type: actionTypes.LOAD_NOTIFICATIONS,
-                               result
-                       });
-                       return Promise.resolve({lastScanned: result.lastScanned});
-               });
-       },
+    fetchUserNotificationsList(dispatch) {
+        return fetch().then(result => {
+            dispatch({
+                type: actionTypes.LOAD_NOTIFICATIONS,
+                result
+            });
+            return Promise.resolve({ lastScanned: result.lastScanned });
+        });
+    },
 
-       loadPreviousNotifications(dispatch, {lastScanned, endOfPage}) {
-               loadPrevNotifications(lastScanned, endOfPage).then(result => dispatch({
-                       type: actionTypes.LOAD_PREV_NOTIFICATIONS,
-                       result
-               }));
-       },
+    loadPreviousNotifications(dispatch, { lastScanned, endOfPage }) {
+        loadPrevNotifications(lastScanned, endOfPage).then(result =>
+            dispatch({
+                type: actionTypes.LOAD_PREV_NOTIFICATIONS,
+                result
+            })
+        );
+    },
 
-       notifyAboutConflicts(dispatch, {itemId, itemName, version, currentScreen}) {
-               let {props} = currentScreen;
-               let currentItemId = props.softwareProductId || props.licenseModelId;
-               let currentVersion = props.version;
-               if(currentItemId === itemId && currentVersion.id === version.id) {
-                       MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId, version}).then(() => ScreensHelper.loadScreen(dispatch, currentScreen));
-               }
-               else {
-                       dispatch({
-                               type: modalActionTypes.GLOBAL_MODAL_WARNING,
-                               data: {
-                                       title: i18n('Conflicts'),
-                                       msg: i18n('There are conflicts in {itemName} version {versionName} that you have to resolve', {itemName: itemName.toUpperCase(), versionName: version.versionName}),
-                                       cancelButtonText: i18n('OK')
-                               }
-                       });
-               }
-       },
+    notifyAboutConflicts(
+        dispatch,
+        { itemId, itemName, version, currentScreen }
+    ) {
+        let { props } = currentScreen;
+        let currentItemId = props.softwareProductId || props.licenseModelId;
+        let currentVersion = props.version;
+        if (currentItemId === itemId && currentVersion.id === version.id) {
+            MergeEditorActionHelper.analyzeSyncResult(dispatch, {
+                itemId,
+                version
+            }).then(() => ScreensHelper.loadScreen(dispatch, currentScreen));
+        } else {
+            dispatch({
+                type: modalActionTypes.GLOBAL_MODAL_WARNING,
+                data: {
+                    title: i18n('Conflicts'),
+                    msg: i18n(
+                        'There are conflicts in {itemName} version {versionName} that you have to resolve',
+                        {
+                            itemName: itemName.toUpperCase(),
+                            versionName: version.versionName
+                        }
+                    ),
+                    cancelButtonText: i18n('OK')
+                }
+            });
+        }
+    },
 
-       syncItem(dispatch, {itemId, itemName, versionId, versionName, currentScreen}) {
-               let version = {id: versionId, versionName};
-               ItemsHelper.fetchVersion({itemId, versionId}).then(response => {
-                       let inMerge = response && response.state && response.state.synchronizationState === SyncStates.MERGE;
-                       if (!inMerge) {
-                               ItemsHelper.performVCAction({itemId, version, action: VersionControllerActionsEnum.SYNC}).then(() => {
-                                       return ItemsHelper.fetchVersion({itemId, versionId}).then(response => {
-                                               let inMerge = response && response.state && response.state.synchronizationState === SyncStates.MERGE;
-                                               if (!inMerge) {
-                                                       return ScreensHelper.loadScreen(dispatch, currentScreen);
-                                               }
-                                               else {
-                                                       return this.notifyAboutConflicts(dispatch, {itemId, itemName, version, currentScreen});
-                                               }
-                                       });
-                               });
-                       }
-                       else {
-                               this.notifyAboutConflicts(dispatch, {itemId, itemName, version, currentScreen});
-                       }
-               });
-       },
+    syncItem(
+        dispatch,
+        { itemId, itemName, versionId, versionName, currentScreen }
+    ) {
+        let version = { id: versionId, versionName };
+        ItemsHelper.fetchVersion({ itemId, versionId }).then(response => {
+            let inMerge =
+                response &&
+                response.state &&
+                response.state.synchronizationState === SyncStates.MERGE;
+            if (!inMerge) {
+                ItemsHelper.performVCAction({
+                    itemId,
+                    version,
+                    action: VersionControllerActionsEnum.SYNC
+                }).then(() => {
+                    return ItemsHelper.fetchVersion({ itemId, versionId }).then(
+                        response => {
+                            let inMerge =
+                                response &&
+                                response.state &&
+                                response.state.synchronizationState ===
+                                    SyncStates.MERGE;
+                            if (!inMerge) {
+                                return ScreensHelper.loadScreen(
+                                    dispatch,
+                                    currentScreen
+                                );
+                            } else {
+                                return this.notifyAboutConflicts(dispatch, {
+                                    itemId,
+                                    itemName,
+                                    version,
+                                    currentScreen
+                                });
+                            }
+                        }
+                    );
+                });
+            } else {
+                this.notifyAboutConflicts(dispatch, {
+                    itemId,
+                    itemName,
+                    version,
+                    currentScreen
+                });
+            }
+        });
+    },
 
-       updateNotification(dispatch, {notificationForUpdate}) {
-               updateNotification(notificationForUpdate.eventId).then(response => {
-                       if(response.status === 'Success' && Object.keys(response.errors).length === 0) {
-                               dispatch({
-                                       type: actionTypes.UPDATE_READ_NOTIFICATION,
-                                       notificationForUpdate
-                               });
-                       }
-               });
-       },
+    updateNotification(dispatch, { notificationForUpdate }) {
+        updateNotification(notificationForUpdate.eventId).then(response => {
+            if (
+                response.status === 'Success' &&
+                Object.keys(response.errors).length === 0
+            ) {
+                dispatch({
+                    type: actionTypes.UPDATE_READ_NOTIFICATION,
+                    notificationForUpdate
+                });
+            }
+        });
+    },
 
-       updateLastSeenNotification(dispatch, {notificationId}) {
-               updateLastSeenNotification(notificationId).then(response => {
-                       if (response.status === 'Success' && Object.keys(response.errors).length === 0) {
-                               dispatch({type: actionTypes.RESET_NEW_NOTIFICATIONS});
-                       }
-               });
-       }
+    updateLastSeenNotification(dispatch, { notificationId }) {
+        updateLastSeenNotification(notificationId).then(response => {
+            if (
+                response.status === 'Success' &&
+                Object.keys(response.errors).length === 0
+            ) {
+                dispatch({ type: actionTypes.RESET_NEW_NOTIFICATIONS });
+            }
+        });
+    }
 };
 
 export default UserNotificationsActionHelper;
index a8e92e2..b2466f1 100644 (file)
@@ -1,22 +1,21 @@
-
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       NOTIFICATION: null,
-       LOAD_NOTIFICATIONS: null,
-       LOAD_PREV_NOTIFICATIONS: null,
-       UPDATE_READ_NOTIFICATION: null,
-       RESET_NEW_NOTIFICATIONS: null,
-       TOGGLE_OVERLAY: null
+    NOTIFICATION: null,
+    LOAD_NOTIFICATIONS: null,
+    LOAD_PREV_NOTIFICATIONS: null,
+    UPDATE_READ_NOTIFICATION: null,
+    RESET_NEW_NOTIFICATIONS: null,
+    TOGGLE_OVERLAY: null
 });
 
 export const notificationType = keyMirror({
-       PERMISSION_CHANGED: 'PermissionChanged',
-       ITEM_CHANGED: {
-               COMMIT: 'commit',
-               SUBMIT: 'submit'
-       },
-       ITEM_DELETED: 'delete',
-       ITEM_ARCHIVED: 'archive',
-       ITEM_RESTORED: 'restore'
-});
\ No newline at end of file
+    PERMISSION_CHANGED: 'PermissionChanged',
+    ITEM_CHANGED: {
+        COMMIT: 'commit',
+        SUBMIT: 'submit'
+    },
+    ITEM_DELETED: 'delete',
+    ITEM_ARCHIVED: 'archive',
+    ITEM_RESTORED: 'restore'
+});
index a2e92fe..98bce1c 100644 (file)
 
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './UsersConstants.js';
+import { actionTypes } from './UsersConstants.js';
 
 function getUserId() {
-       let catalogApiHeaders = Configuration.get('CatalogApiHeaders');
-       let User = catalogApiHeaders && catalogApiHeaders.userId;
-       let userId = User && User.value ? User.value : '';
-       return userId;
+    let catalogApiHeaders = Configuration.get('CatalogApiHeaders');
+    let User = catalogApiHeaders && catalogApiHeaders.userId;
+    let userId = User && User.value ? User.value : '';
+    return userId;
 }
 
 function baseUrl() {
-       const restCatalogPrefix = Configuration.get('restCatalogPrefix');
-       return `${restCatalogPrefix}`;
+    const restCatalogPrefix = Configuration.get('restCatalogPrefix');
+    return `${restCatalogPrefix}`;
 }
 
-
 function fetchUsersList() {
-       const url = '/v1/user/users';
-       return  RestAPIUtil.fetch(`${baseUrl()}${url}`);
+    const url = '/v1/user/users';
+    return RestAPIUtil.fetch(`${baseUrl()}${url}`);
 }
 
-
-
 const UsersActionHelper = {
-       fetchUsersList(dispatch) {
-               fetchUsersList().then(response => {
-                       dispatch({
-                               type: actionTypes.USERS_LIST_LOADED,
-                               usersList: response
-                       });
-
-                       let userId = getUserId();
-                       let userInfo = response.find(user => user.userId === userId);
-                       dispatch({
-                               type: actionTypes.GOT_USER_INFO,
-                               userInfo
-                       });
-
-               });
-
-       }
+    fetchUsersList(dispatch) {
+        fetchUsersList().then(response => {
+            dispatch({
+                type: actionTypes.USERS_LIST_LOADED,
+                usersList: response
+            });
+
+            let userId = getUserId();
+            let userInfo = response.find(user => user.userId === userId);
+            dispatch({
+                type: actionTypes.GOT_USER_INFO,
+                userInfo
+            });
+        });
+    }
 };
 
 export default UsersActionHelper;
index fdcf4b1..216d28a 100644 (file)
@@ -17,6 +17,6 @@
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       USERS_LIST_LOADED: null,
-       GOT_USER_INFO: null
+    USERS_LIST_LOADED: null,
+    GOT_USER_INFO: null
 });
index 6bd72e3..89a04d2 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {actionTypes} from './UsersConstants.js';
-import {combineReducers} from 'redux';
+import { actionTypes } from './UsersConstants.js';
+import { combineReducers } from 'redux';
 
-function usersList (state = [], action) {
-       switch (action.type) {
-               case (actionTypes.USERS_LIST_LOADED):
-                       return [...action.usersList];
-               default:
-                       return state;
-       }
-};
-
-function userInfo (state = {}, action) {
-       switch (action.type) {
-               case (actionTypes.GOT_USER_INFO):
-                       return action.userInfo;
-               default:
-                       return state;
-       }
+function usersList(state = [], action) {
+    switch (action.type) {
+        case actionTypes.USERS_LIST_LOADED:
+            return [...action.usersList];
+        default:
+            return state;
+    }
 }
 
+function userInfo(state = {}, action) {
+    switch (action.type) {
+        case actionTypes.GOT_USER_INFO:
+            return action.userInfo;
+        default:
+            return state;
+    }
+}
 
 export default combineReducers({
-       usersList: usersList,
-       userInfo: userInfo
-});
\ No newline at end of file
+    usersList: usersList,
+    userInfo: userInfo
+});
index 0fd0eab..457d096 100644 (file)
  * permissions and limitations under the License.
  */
 
-import {connect} from 'react-redux';
+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 { 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, isArchived}, props: {itemId}},
-       softwareProductList = []
+    users: { userInfo },
+    versionsPage: { permissions, versionsList },
+    currentScreen: {
+        itemPermission: { isCollaborator, isArchived },
+        props: { itemId }
+    },
+    softwareProductList = []
 }) => {
+    let { versions = [], selectedVersion } = versionsList;
+    let { owner, contributors, viewers } = permissions;
 
-       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,
-               isArchived
-       };
-
+    // 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,
+        isArchived
+    };
 };
 
-export const mapActionsToProps = (dispatch, {itemType, itemId, additionalProps}) => {
-       return {
-               onNavigateToVersion({version}) {
-                       VersionsPageActionHelper.onNavigateToVersion(dispatch, {version, itemId, itemType, additionalProps});
-               },
+export const mapActionsToProps = (
+    dispatch,
+    { itemType, itemId, additionalProps }
+) => {
+    return {
+        onNavigateToVersion({ version }) {
+            VersionsPageActionHelper.onNavigateToVersion(dispatch, {
+                version,
+                itemId,
+                itemType,
+                additionalProps
+            });
+        },
 
-               onSelectVersion({version}) {
-                       VersionsPageActionHelper.selectVersion(dispatch, {version});
-               },
+        onSelectVersion({ version }) {
+            VersionsPageActionHelper.selectVersion(dispatch, { version });
+        },
 
-               onCreateVersion({version}) {
-                       VersionsPageCreationActionHelper.open(dispatch, {baseVersion: version, itemId, itemType, additionalProps});
-               },
+        onCreateVersion({ version }) {
+            VersionsPageCreationActionHelper.open(dispatch, {
+                baseVersion: version,
+                itemId,
+                itemType,
+                additionalProps
+            });
+        },
 
-               onManagePermissions() {
-                       PermissionsActionHelper.openPermissonsManager(dispatch, {itemId, askForRights: false});
-               },
+        onManagePermissions() {
+            PermissionsActionHelper.openPermissonsManager(dispatch, {
+                itemId,
+                askForRights: false
+            });
+        },
 
-               onTreeFullScreen(treeProps) {
-                       VersionsPageActionHelper.openTree(dispatch, treeProps);
-               },
+        onTreeFullScreen(treeProps) {
+            VersionsPageActionHelper.openTree(dispatch, treeProps);
+        },
 
-               onModalNodeClick({version}) {
-                       VersionsPageActionHelper.selectVersionFromModal(dispatch, {version});
-               },
-               onArchive: () => VersionsPageActionHelper.archiveItem(dispatch, itemId),
-               onRestore: () => VersionsPageActionHelper.restoreItemFromArchive(dispatch, itemId)
-       };
+        onModalNodeClick({ version }) {
+            VersionsPageActionHelper.selectVersionFromModal(dispatch, {
+                version
+            });
+        },
+        onArchive: () => VersionsPageActionHelper.archiveItem(dispatch, itemId),
+        onRestore: () =>
+            VersionsPageActionHelper.restoreItemFromArchive(dispatch, itemId)
+    };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(VersionsPageView);
index f8417fa..7f7af81 100644 (file)
@@ -22,81 +22,144 @@ import Button from 'sdc-ui/lib/react/Button.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import featureToggle from 'sdc-app/features/featureToggle.js';
 
-const DepricateButton = ({depricateAction, title}) => (
-       <div className='depricate-btn-wrapper'>
-               <Button data-test-id='depricate-action-btn'     className='depricate-btn' onClick={depricateAction}>{title}</Button>
-       </div>
+const DepricateButton = ({ depricateAction, title }) => (
+    <div className="depricate-btn-wrapper">
+        <Button
+            data-test-id="depricate-action-btn"
+            className="depricate-btn"
+            onClick={depricateAction}>
+            {title}
+        </Button>
+    </div>
 );
 
-const FeatureDepricatedButton = featureToggle('ARCHIVE_ITEM')(DepricateButton);        
+const FeatureDepricatedButton = featureToggle('ARCHIVE_ITEM')(DepricateButton);
 
-const VersionPageTitle = ({itemName, depricatedTitle, isArchived, onRestore, onArchive}) => {
-       return (
-               <div className='version-page-header'>
-                       <div className='versions-page-title'>{`${i18n('Available Versions')} - ${itemName}  ${depricatedTitle}`}</div>                  
-                       <FeatureDepricatedButton depricateAction={isArchived ? () => onRestore() : () => onArchive() }  title={i18n(isArchived ? 'RESTORE' : 'ARCHIVE')}/>
-               </div>
-       );
+const VersionPageTitle = ({
+    itemName,
+    depricatedTitle,
+    isArchived,
+    onRestore,
+    onArchive
+}) => {
+    return (
+        <div className="version-page-header">
+            <div className="versions-page-title">{`${i18n(
+                'Available Versions'
+            )} - ${itemName}  ${depricatedTitle}`}</div>
+            <FeatureDepricatedButton
+                depricateAction={
+                    isArchived ? () => onRestore() : () => onArchive()
+                }
+                title={i18n(isArchived ? 'RESTORE' : 'ARCHIVE')}
+            />
+        </div>
+    );
 };
 
 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, isArchived, onArchive, onRestore} = this.props;            
-               const depricatedTitle = isArchived ? i18n('(Archived)') : '';
-               return (
-                       <div className='versions-page-view'>
-                               <VersionPageTitle 
-                                       itemName={itemName} 
-                                       depricatedTitle={depricatedTitle}                                       
-                                       onArchive={onArchive}
-                                       isArchived={isArchived}
-                                       onRestore={onRestore}/>
-                               <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={isArchived ? false : onCreateVersion}
-                                               selectedVersion={selectedVersion}
-                                               isCollaborator={isCollaborator} />
-                               </div>
-                       </div>
-               );
-       }
+    state = {
+        showExpanded: false
+    };
+    render() {
+        let {
+            versions,
+            owner,
+            contributors,
+            currentUser,
+            isCollaborator,
+            itemName = '',
+            viewers,
+            onSelectVersion,
+            onNavigateToVersion,
+            onTreeFullScreen,
+            onManagePermissions,
+            onCreateVersion,
+            selectedVersion,
+            onModalNodeClick,
+            isManual,
+            isArchived,
+            onArchive,
+            onRestore
+        } = this.props;
+        const depricatedTitle = isArchived ? i18n('(Archived)') : '';
+        return (
+            <div className="versions-page-view">
+                <VersionPageTitle
+                    itemName={itemName}
+                    depricatedTitle={depricatedTitle}
+                    onArchive={onArchive}
+                    isArchived={isArchived}
+                    onRestore={onRestore}
+                />
+                <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={isArchived ? false : onCreateVersion}
+                        selectedVersion={selectedVersion}
+                        isCollaborator={isCollaborator}
+                    />
+                </div>
+            </div>
+        );
+    }
 }
 
 export default VersionsPage;
index d475c03..606b17b 100644 (file)
  * 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 { 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';
-
+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
-                       });
-                       return Promise.resolve(response);
-               });
-       },
+    fetchVersions(dispatch, { itemType, itemId }) {
+        return ItemsHelper.fetchVersions({ itemId }).then(response => {
+            dispatch({
+                type: actionTypes.VERSIONS_LOADED,
+                versions: response.results,
+                itemType,
+                itemId
+            });
+            return Promise.resolve(response);
+        });
+    },
 
-       selectVersion(dispatch, {version}) {
-               dispatch({
-                       type: actionTypes.SELECT_VERSION,
-                       versionId: version.id
-               });
-       },
+    selectVersion(dispatch, { version }) {
+        dispatch({
+            type: actionTypes.SELECT_VERSION,
+            versionId: version.id
+        });
+    },
 
-       selectNone(dispatch) {
-               dispatch({ type: actionTypes.SELECT_NONE });
-       },
+    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;
-               }
-       },
+    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')
-                       }
-               });
-       },
+    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});
-       },
+    selectVersionFromModal(dispatch, { version }) {
+        dispatch({
+            type: modalActionTypes.GLOBAL_MODAL_CLOSE
+        });
+        this.selectVersion(dispatch, { version });
+    },
 
-       archiveItem(dispatch, itemId) {
-               ItemsHelper.archiveItem(itemId).then(() => {
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: enums.SCREEN.ONBOARDING_CATALOG
-                       });
-               });     
-       },
+    archiveItem(dispatch, itemId) {
+        ItemsHelper.archiveItem(itemId).then(() => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.ONBOARDING_CATALOG
+            });
+        });
+    },
 
-       restoreItemFromArchive(dispatch, itemId) {
-               ItemsHelper.restoreItem(itemId).then(() => {
-                       ScreensHelper.loadScreen(dispatch, {
-                               screen: enums.SCREEN.ONBOARDING_CATALOG
-                       });
-               });
-       }
+    restoreItemFromArchive(dispatch, itemId) {
+        ItemsHelper.restoreItem(itemId).then(() => {
+            ScreensHelper.loadScreen(dispatch, {
+                screen: enums.SCREEN.ONBOARDING_CATALOG
+            });
+        });
+    }
 };
 
 export default VersionsPageActionHelper;
index 983ab79..3a3879d 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       VERSIONS_LOADED: null,
-       SELECT_VERSION: null,
-       SELECT_NONE: null
+    VERSIONS_LOADED: null,
+    SELECT_VERSION: null,
+    SELECT_NONE: null
 });
 
 export const itemTypes = {
-       LICENSE_MODEL: 'vendor-license-models',
-       SOFTWARE_PRODUCT: 'vendor-software-products'
+    LICENSE_MODEL: 'vendor-license-models',
+    SOFTWARE_PRODUCT: 'vendor-software-products'
 };
index 9b6fa9f..c270278 100644 (file)
  * 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 { 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';
+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;
-       }
-};
-
-
+    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
+    versionCreation: createPlainDataReducer(VersionsPageCreationReducer),
+    versionsList: VersionsListReducer,
+    permissions: PermissionsReducer
 });
index 26f8450..74d88f0 100644 (file)
@@ -22,61 +22,108 @@ 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>
-       );
+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 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 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 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>
+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;
index 47255eb..d74805e 100644 (file)
@@ -20,108 +20,177 @@ 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 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);
+    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;
+    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>;
+    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 }) => {
+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');
 
-       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 && onCreateVersion &&
-                                                                       <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 || !onCreateVersion} />
-                                                               }
-                                                       </div>
-                                               </div>
-                               }
-               </div>
-       );
+    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 &&
+                            onCreateVersion && (
+                                <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 || !onCreateVersion
+                                    }
+                                />
+                            )}
+                    </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 ? () => onCreateVersion({version}) : false}
-                                       isSelected={selectedVersion === version.id}
-                                       isCollaborator={isCollaborator} />
-                       )}
-               </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
+                            ? () => onCreateVersion({ version })
+                            : false
+                    }
+                    isSelected={selectedVersion === version.id}
+                    isCollaborator={isCollaborator}
+                />
+            ))}
+        </div>
+    </div>
 );
 
 export default VersionList;
index 66c1c79..e0cb925 100644 (file)
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-import {connect} from 'react-redux';
+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';
+import { VERSION_CREATION_FORM_NAME } from './VersionsPageCreationConstants.js';
 
-export const mapStateToProps = ({versionsPage: {versionCreation}}) => {
-       let {genericFieldInfo} = versionCreation;
-       let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+export const mapStateToProps = ({ versionsPage: { versionCreation } }) => {
+    let { genericFieldInfo } = versionCreation;
+    let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
-       return {...versionCreation, isFormValid};
+    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 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);
+export default connect(mapStateToProps, mapActionsToProps)(
+    VersionsPageCreationView
+);
index bc03868..6e3be70 100644 (file)
  */
 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 { 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';
+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 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});
+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
+        });
 
-       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_SHOW,
+            data: {
+                modalComponentName: modalContentMapper.VERSION_CREATION,
+                modalComponentProps: {
+                    itemType,
+                    itemId,
+                    additionalProps,
+                    baseVersion
+                },
+                title: i18n('New Version - From {name}', {
+                    name: baseVersion.name
+                })
+            }
+        });
+    },
 
-               dispatch({
-                       type: modalActionTypes.GLOBAL_MODAL_CLOSE
-               });
-       },
+    close(dispatch) {
+        dispatch({
+            type: actionTypes.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;
-                       });
-               });
-       }
+        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;
+            });
+        });
+    }
 };
index 4ce381d..e761232 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-       OPEN: null,
-       CLOSE: null,
-       VERSION_CREATED: null
+    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
+    creationMethod: 'major'
+};
index 620cf47..a762e4d 100644 (file)
  * 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';
+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;
-       }
+    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;
+    }
 };
index caa85fe..ba92d26 100644 (file)
@@ -20,125 +20,116 @@ 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
+    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();
-       }
-
+    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
index b467e3c..b759ffd 100644 (file)
@@ -25,9 +25,18 @@ import Application from './Application.jsx';
 import Modules from './ModulesOptions.jsx';
 
 //chrome 48 remove svg method which is used in jointjs core -> https://github.com/cpettitt/dagre-d3/issues/202 --> http://jointjs.com/blog/get-transform-to-element-polyfill.html
-SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(toElement) {
-       return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
-};
-
-ReactDOM.render(<Application><Modules/></Application>, document.getElementById('sdc-app'));
+SVGElement.prototype.getTransformToElement =
+    SVGElement.prototype.getTransformToElement ||
+    function(toElement) {
+        return toElement
+            .getScreenCTM()
+            .inverse()
+            .multiply(this.getScreenCTM());
+    };
 
+ReactDOM.render(
+    <Application>
+        <Modules />
+    </Application>,
+    document.getElementById('sdc-app')
+);
index d1038b6..5506670 100644 (file)
@@ -4,41 +4,77 @@ let path = require('path');
 
 let localDevConfig = {};
 try {
-       localDevConfig = require('./devConfig');
+    localDevConfig = require('./devConfig');
 } catch (e) {
-       console.log('Could not find local dev config.');
+    console.log('Could not find local dev config.');
 }
-let devConfig = Object.assign({}, require('./devConfig.defaults'), localDevConfig);
+let devConfig = Object.assign(
+    {},
+    require('./devConfig.defaults'),
+    localDevConfig
+);
 module.exports = {
-       entry: devConfig.bundles,
-       resolve: {
-               modules: [path.resolve('.'), path.join(__dirname, 'node_modules')],
-               alias: {
-                       i18nJson: 'nfvo-utils/i18n/en.json', // only for default build, not through gulp
-                       'nfvo-utils': 'src/nfvo-utils',
-                       'nfvo-components': 'src/nfvo-components',
-                       'sdc-app': 'src/sdc-app',
-                       'react-select/dist/' : 'node_modules/react-select/dist/',
-                       'jquery' : 'node_modules/restful-js/node_modules/jquery'
-               }
-       },
-       module: {
-               rules: [
-                       {test: /\.(js|jsx)$/, loader: 'source-map-loader', exclude: [/node_modules/, path.resolve(__dirname, '../dox-sequence-diagram/')], enforce: 'pre'},
-                       {test: /\.(js|jsx)$/, use: [
-                               {loader : 'babel-loader'},
-                               {loader : 'eslint-loader'}], exclude: [/node_modules/, path.resolve(__dirname, '../dox-sequence-diagram/')]},
-                       {test: /\.(css|scss)$/, use: [
-                               {loader: 'style-loader'},
-                               {loader: 'css-loader?sourceMap'},
-                               {loader: 'sass-loader?sourceMap', options: { output: { path: path.join(__dirname, 'dist') } }}]},
+    entry: devConfig.bundles,
+    resolve: {
+        modules: [path.resolve('.'), path.join(__dirname, 'node_modules')],
+        alias: {
+            i18nJson: 'nfvo-utils/i18n/en.json', // only for default build, not through gulp
+            'nfvo-utils': 'src/nfvo-utils',
+            'nfvo-components': 'src/nfvo-components',
+            'sdc-app': 'src/sdc-app',
+            'react-select/dist/': 'node_modules/react-select/dist/',
+            jquery: 'node_modules/restful-js/node_modules/jquery'
+        }
+    },
+    module: {
+        rules: [
+            {
+                test: /\.(js|jsx)$/,
+                loader: 'source-map-loader',
+                exclude: [
+                    /node_modules/,
+                    path.resolve(__dirname, '../dox-sequence-diagram/')
+                ],
+                enforce: 'pre'
+            },
+            {
+                test: /\.(js|jsx)$/,
+                use: [
+                    { loader: 'babel-loader' },
+                    { loader: 'eslint-loader', options: { fix: false } }
+                ],
+                exclude: [
+                    /node_modules/,
+                    path.resolve(__dirname, '../dox-sequence-diagram/')
+                ]
+            },
+            {
+                test: /\.(css|scss)$/,
+                use: [
+                    { loader: 'style-loader' },
+                    { loader: 'css-loader?sourceMap' },
+                    {
+                        loader: 'sass-loader?sourceMap',
+                        options: {
+                            output: { path: path.join(__dirname, 'dist') }
+                        }
+                    }
+                ]
+            },
 
-                       // required for font icons
-                       {test: /\.(woff|woff2)(\?.*)?$/, loader: 'url-loader?limit=16384&mimetype=application/font-woff'},
-                       {test: /\.(ttf|eot|otf)(\?.*)?$/, loader: 'file-loader'},
-                       {test: /\.(png|jpg|svg)(\?.*)?$/, loader: 'url-loader?limit=16384', exclude: path.join(__dirname, 'resources/images/svg') },
-                       {test: /\.html$/, use: [ {loader: 'html-loader'}]}
-               ]
-       },
-       plugins: []
+            // required for font icons
+            {
+                test: /\.(woff|woff2)(\?.*)?$/,
+                loader: 'url-loader?limit=16384&mimetype=application/font-woff'
+            },
+            { test: /\.(ttf|eot|otf)(\?.*)?$/, loader: 'file-loader' },
+            {
+                test: /\.(png|jpg|svg)(\?.*)?$/,
+                loader: 'url-loader?limit=16384',
+                exclude: path.join(__dirname, 'resources/images/svg')
+            },
+            { test: /\.html$/, use: [{ loader: 'html-loader' }] }
+        ]
+    },
+    plugins: []
 };
index 2dea217..22da77e 100644 (file)
@@ -10,48 +10,57 @@ let webpackCommon = require('./webpack.common');
 // copying the common config
 let webpackProdConfig = cloneDeep(webpackCommon);
 // setting production settings
-assign( webpackProdConfig, {
-       devtool: undefined,
-       cache: true,
-       output: {
-               path: path.join(__dirname, 'dist'),
-               publicPath: '/onboarding/',
-               filename: '[name].js'
-       },
-       resolveLoader: {
-               modules: [path.join(__dirname, 'node_modules'), path.resolve('.')],
-               alias: {
-                       'config-json-loader': 'tools/webpack/config-json-loader/index.js'
-               }
-       },
-       plugins: [
-               new webpack.DefinePlugin({
-                       'process.env': {
-                               // This has effect on the react lib size
-                               'NODE_ENV': JSON.stringify('production')
-                       },
-                       DEBUG: false,
-                       DEV: false
-               }),
-               new webpack.optimize.UglifyJsPlugin(),
-               new webpack.LoaderOptionsPlugin({
-                       options: {
-                               eslint: {
-                                       configFile: './.eslintrc',
-                                       emitError: true,
-                                       emitWarning: true,
-                                       failOnError: true
-                               }
-                       }
-               })
-       ]
+assign(webpackProdConfig, {
+    devtool: undefined,
+    cache: true,
+    output: {
+        path: path.join(__dirname, 'dist'),
+        publicPath: '/onboarding/',
+        filename: '[name].js'
+    },
+    resolveLoader: {
+        modules: [path.join(__dirname, 'node_modules'), path.resolve('.')],
+        alias: {
+            'config-json-loader': 'tools/webpack/config-json-loader/index.js'
+        }
+    },
+    plugins: [
+        new webpack.DefinePlugin({
+            'process.env': {
+                // This has effect on the react lib size
+                NODE_ENV: JSON.stringify('production')
+            },
+            DEBUG: false,
+            DEV: false
+        }),
+        new webpack.optimize.UglifyJsPlugin(),
+        new webpack.LoaderOptionsPlugin({
+            options: {
+                eslint: {
+                    configFile: './.eslintrc',
+                    emitError: true,
+                    emitWarning: true,
+                    failOnError: true
+                }
+            }
+        })
+    ]
 });
 
-webpackProdConfig.module.rules = webpackProdConfig.module.rules.filter(rule => ((rule.enforce !== 'pre') || (rule.enforce === 'pre' && rule.loader !== 'source-map-loader')));
+webpackProdConfig.module.rules = webpackProdConfig.module.rules.filter(
+    rule =>
+        rule.enforce !== 'pre' ||
+        (rule.enforce === 'pre' && rule.loader !== 'source-map-loader')
+);
 webpackProdConfig.module.rules.forEach(loader => {
-       if (loader.use && loader.use[0].loader === 'style-loader') {
-               loader.use = loader.use.map(loaderObj => loaderObj.loader.replace('?sourceMap', ''));
-       }
+    if (loader.use && loader.use[0].loader === 'style-loader') {
+        loader.use = loader.use.map(loaderObj =>
+            loaderObj.loader.replace('?sourceMap', '')
+        );
+    }
+});
+webpackProdConfig.module.rules.push({
+    test: /config.json$/,
+    use: [{ loader: 'config-json-loader' }]
 });
-webpackProdConfig.module.rules.push({test: /config.json$/, use: [{loader:'config-json-loader'}]});
 module.exports = webpackProdConfig;
index fe991f3..e7b68d1 100644 (file)
 # yarn lockfile v1
 
 
-"@angular/common@2.3.1":
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/@angular/common/-/common-2.3.1.tgz#146c2ed44e02b0f291dd9d4b2e5e2a693057e9bc"
+"@angular/common@~2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/common/-/common-2.4.10.tgz#a3a682d2228fa30ec23dd0eb57c8e887fba26997"
 
-"@angular/core@2.3.1":
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/@angular/core/-/core-2.3.1.tgz#be6e91fdfdd7498506604263e051797cf67a47be"
+"@angular/core@~2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/core/-/core-2.4.10.tgz#0b8320a65065965d998645b1f5cd3cf769b441ea"
 
-"@angular/platform-browser-dynamic@2.3.1":
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-2.3.1.tgz#d01f3c0c25c628be83c308e83d53128222f558fa"
+"@angular/forms@~2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-2.4.10.tgz#062133aaade1f3b3c962f1593208c541b622fd06"
 
-"@angular/platform-browser@2.3.1":
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-2.3.1.tgz#114309150876188e0df8841b20ca2359fd5e7cad"
+"@angular/http@^2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/http/-/http-2.4.10.tgz#ff6beade5b39c989ebf2393c49b34eebd43e9555"
+
+"@angular/platform-browser-dynamic@~2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-2.4.10.tgz#8df25dec2b06adc690cc9bc26448deccaebcd8ec"
+
+"@angular/platform-browser@~2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-2.4.10.tgz#cbf25608148fb4ffef96cc5005ba5d7b3e093906"
 
 "@angular/router@~3.2.1":
   version "3.2.4"
   resolved "https://registry.yarnpkg.com/@angular/router/-/router-3.2.4.tgz#dfec71ad072ec031364ba5d08bd6fe03fd5beadc"
 
+"@angular/upgrade@^2.4.8":
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/@angular/upgrade/-/upgrade-2.4.10.tgz#b69a3ee324d4450eb1696ddc9bded1a6ec06ca52"
+
+"@babel/code-frame@7.0.0-beta.40", "@babel/code-frame@^7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz#37e2b0cf7c56026b4b21d3927cadf81adec32ac6"
+  dependencies:
+    "@babel/highlight" "7.0.0-beta.40"
+
+"@babel/generator@7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.40.tgz#ab61f9556f4f71dbd1138949c795bb9a21e302ea"
+  dependencies:
+    "@babel/types" "7.0.0-beta.40"
+    jsesc "^2.5.1"
+    lodash "^4.2.0"
+    source-map "^0.5.0"
+    trim-right "^1.0.1"
+
+"@babel/helper-function-name@7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.40.tgz#9d033341ab16517f40d43a73f2d81fc431ccd7b6"
+  dependencies:
+    "@babel/helper-get-function-arity" "7.0.0-beta.40"
+    "@babel/template" "7.0.0-beta.40"
+    "@babel/types" "7.0.0-beta.40"
+
+"@babel/helper-get-function-arity@7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.40.tgz#ac0419cf067b0ec16453e1274f03878195791c6e"
+  dependencies:
+    "@babel/types" "7.0.0-beta.40"
+
+"@babel/highlight@7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.40.tgz#b43d67d76bf46e1d10d227f68cddcd263786b255"
+  dependencies:
+    chalk "^2.0.0"
+    esutils "^2.0.2"
+    js-tokens "^3.0.0"
+
+"@babel/template@7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.40.tgz#034988c6424eb5c3268fe6a608626de1f4410fc8"
+  dependencies:
+    "@babel/code-frame" "7.0.0-beta.40"
+    "@babel/types" "7.0.0-beta.40"
+    babylon "7.0.0-beta.40"
+    lodash "^4.2.0"
+
+"@babel/traverse@^7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.40.tgz#d140e449b2e093ef9fe1a2eecc28421ffb4e521e"
+  dependencies:
+    "@babel/code-frame" "7.0.0-beta.40"
+    "@babel/generator" "7.0.0-beta.40"
+    "@babel/helper-function-name" "7.0.0-beta.40"
+    "@babel/types" "7.0.0-beta.40"
+    babylon "7.0.0-beta.40"
+    debug "^3.0.1"
+    globals "^11.1.0"
+    invariant "^2.2.0"
+    lodash "^4.2.0"
+
+"@babel/types@7.0.0-beta.40", "@babel/types@^7.0.0-beta.40":
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.40.tgz#25c3d7aae14126abe05fcb098c65a66b6d6b8c14"
+  dependencies:
+    esutils "^2.0.2"
+    lodash "^4.2.0"
+    to-fast-properties "^2.0.0"
+
 "@kadira/react-split-pane@^1.4.0":
   version "1.4.7"
   resolved "https://registry.yarnpkg.com/@kadira/react-split-pane/-/react-split-pane-1.4.7.tgz#6d753d4a9fe62fe82056e323a6bcef7f026972b5"
@@ -365,6 +446,10 @@ acorn@^5.0.0, acorn@^5.2.1:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822"
 
+acorn@^5.4.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.0.tgz#1abb587fbf051f94e3de20e6b26ef910b1828298"
+
 airbnb-js-shims@^1.0.1, airbnb-js-shims@^1.4.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-1.4.1.tgz#cc3e8eb8d35877f9d0fdc6583e26b0ee75b98ad0"
@@ -382,7 +467,7 @@ airbnb-js-shims@^1.0.1, airbnb-js-shims@^1.4.0:
     string.prototype.padend "^3.0.0"
     string.prototype.padstart "^3.0.0"
 
-ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
+ajv-keywords@^1.1.1:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
 
@@ -390,6 +475,10 @@ ajv-keywords@^2.0.0, ajv-keywords@^2.1.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
 
+ajv-keywords@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be"
+
 ajv@^4.7.0, ajv@^4.9.1:
   version "4.11.8"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
@@ -397,7 +486,7 @@ ajv@^4.7.0, ajv@^4.9.1:
     co "^4.6.0"
     json-stable-stringify "^1.0.1"
 
-ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5:
+ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5, ajv@^5.3.0:
   version "5.5.2"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
   dependencies:
@@ -406,6 +495,14 @@ ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5:
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
 
+ajv@^6.0.1:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.0.tgz#afac295bbaa0152449e522742e4547c1ae9328d2"
+  dependencies:
+    fast-deep-equal "^1.0.0"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.3.0"
+
 align-text@^0.1.1, align-text@^0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
@@ -434,10 +531,6 @@ ansi-cyan@^0.1.1:
   dependencies:
     ansi-wrap "0.1.0"
 
-ansi-escapes@^1.1.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
-
 ansi-escapes@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
@@ -804,14 +897,16 @@ babel-core@^6.0.0, babel-core@^6.11.4, babel-core@^6.24.0, babel-core@^6.26.0:
     slash "^1.0.0"
     source-map "^0.5.6"
 
-babel-eslint@^7.2.1:
-  version "7.2.3"
-  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827"
+babel-eslint@^8.2.1:
+  version "8.2.2"
+  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b"
   dependencies:
-    babel-code-frame "^6.22.0"
-    babel-traverse "^6.23.1"
-    babel-types "^6.23.0"
-    babylon "^6.17.0"
+    "@babel/code-frame" "^7.0.0-beta.40"
+    "@babel/traverse" "^7.0.0-beta.40"
+    "@babel/types" "^7.0.0-beta.40"
+    babylon "^7.0.0-beta.40"
+    eslint-scope "~3.7.1"
+    eslint-visitor-keys "^1.0.0"
 
 babel-generator@^6.18.0, babel-generator@^6.26.0:
   version "6.26.0"
@@ -1877,12 +1972,6 @@ babel-register@^6.26.0:
     mkdirp "^0.5.1"
     source-map-support "^0.4.15"
 
-babel-runtime@5.8.19:
-  version "5.8.19"
-  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-5.8.19.tgz#05ee3aaf67e6d4a39f1bc0f07598b26b9ceb4d3e"
-  dependencies:
-    core-js "^0.9.0"
-
 babel-runtime@6.11.6:
   version "6.11.6"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.11.6.tgz#6db707fef2d49c49bfa3cb64efdb436b518b8222"
@@ -1907,7 +1996,7 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-te
     babylon "^6.18.0"
     lodash "^4.17.4"
 
-babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0, babel-traverse@^6.4.5:
+babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0, babel-traverse@^6.4.5:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
   dependencies:
@@ -1921,7 +2010,7 @@ babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-tr
     invariant "^2.2.2"
     lodash "^4.17.4"
 
-babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
   dependencies:
@@ -1930,7 +2019,11 @@ babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23
     lodash "^4.17.4"
     to-fast-properties "^1.0.3"
 
-babylon@^6.17.0, babylon@^6.18.0, babylon@^6.4.5:
+babylon@7.0.0-beta.40, babylon@^7.0.0-beta.40:
+  version "7.0.0-beta.40"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.40.tgz#91fc8cd56d5eb98b28e6fde41045f2957779940a"
+
+babylon@^6.18.0, babylon@^6.4.5:
   version "6.18.0"
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
 
@@ -2207,7 +2300,7 @@ buffer@^4.3.0, buffer@^4.9.0:
     ieee754 "^1.1.4"
     isarray "^1.0.0"
 
-builtin-modules@^1.0.0:
+builtin-modules@^1.0.0, builtin-modules@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
 
@@ -2359,6 +2452,14 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
     strip-ansi "^3.0.0"
     supports-color "^2.0.0"
 
+chalk@^2.0.0, chalk@^2.1.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
+  dependencies:
+    ansi-styles "^3.2.0"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.2.0"
+
 chalk@^2.0.1, chalk@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
@@ -2367,6 +2468,10 @@ chalk@^2.0.1, chalk@^2.3.0:
     escape-string-regexp "^1.0.5"
     supports-color "^4.0.0"
 
+chardet@^0.4.0:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+
 charenc@~0.0.1:
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@@ -2478,11 +2583,11 @@ clean-css@4.1.x:
   dependencies:
     source-map "0.5.x"
 
-cli-cursor@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
   dependencies:
-    restore-cursor "^1.0.1"
+    restore-cursor "^2.0.0"
 
 cli-width@^2.0.0:
   version "2.2.0"
@@ -2681,7 +2786,7 @@ concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
 
-concat-stream@^1.4.6, concat-stream@^1.5.0:
+concat-stream@^1.5.0, concat-stream@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
   dependencies:
@@ -2732,6 +2837,10 @@ constants-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
 
+contains-path@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
+
 content-disposition@0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
@@ -2771,10 +2880,6 @@ copy-descriptor@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
 
-core-js@^0.9.0:
-  version "0.9.18"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-0.9.18.tgz#13f458e430232b0f4ec1f480da7c2f5288e9d095"
-
 core-js@^1.0.0:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@ -2841,7 +2946,7 @@ cross-spawn@^3.0.0:
     lru-cache "^4.0.1"
     which "^1.2.9"
 
-cross-spawn@^5.0.1:
+cross-spawn@^5.0.1, cross-spawn@^5.1.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
   dependencies:
@@ -3315,13 +3420,13 @@ dateformat@^2.0.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
 
-debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8:
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
   dependencies:
     ms "2.0.0"
 
-debug@^3.1.0:
+debug@^3.0.1, debug@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
   dependencies:
@@ -3511,14 +3616,14 @@ dns-txt@^2.0.2:
   dependencies:
     buffer-indexof "^1.0.0"
 
-doctrine@^1.2.2:
+doctrine@1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
   dependencies:
     esutils "^2.0.2"
     isarray "^1.0.0"
 
-doctrine@^2.0.0:
+doctrine@^2.0.0, doctrine@^2.0.2, doctrine@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
   dependencies:
@@ -3879,9 +3984,22 @@ escope@^3.6.0:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
-eslint-loader@^1.3.0:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-1.9.0.tgz#7e1be9feddca328d3dcfaef1ad49d5beffe83a13"
+eslint-config-prettier@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3"
+  dependencies:
+    get-stdin "^5.0.1"
+
+eslint-import-resolver-node@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
+  dependencies:
+    debug "^2.6.9"
+    resolve "^1.5.0"
+
+eslint-loader@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-2.0.0.tgz#d136619b5c684e36531ffc28c60a56e404608f5d"
   dependencies:
     loader-fs-cache "^1.0.0"
     loader-utils "^1.0.2"
@@ -3889,65 +4007,102 @@ eslint-loader@^1.3.0:
     object-hash "^1.1.4"
     rimraf "^2.6.1"
 
-eslint-plugin-import@^0.8.1:
-  version "0.8.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-0.8.1.tgz#c1e076097d913cbdfd58f1d14f49205d8a33a735"
+eslint-module-utils@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
   dependencies:
-    babel-runtime "5.8.19"
-    espree "^2.0.1"
-    resolve "^1.1.6"
+    debug "^2.6.8"
+    pkg-dir "^1.0.0"
 
-eslint-plugin-react@^3.14.0:
-  version "3.16.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-3.16.1.tgz#262d96b77d7c4a42af809a73c0e527a58612293c"
+eslint-plugin-import@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz#26002efbfca5989b7288ac047508bd24f217b169"
+  dependencies:
+    builtin-modules "^1.1.1"
+    contains-path "^0.1.0"
+    debug "^2.6.8"
+    doctrine "1.5.0"
+    eslint-import-resolver-node "^0.3.1"
+    eslint-module-utils "^2.1.1"
+    has "^1.0.1"
+    lodash "^4.17.4"
+    minimatch "^3.0.3"
+    read-pkg-up "^2.0.0"
 
-eslint@^2.13.1:
-  version "2.13.1"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11"
+eslint-plugin-prettier@^2.6.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
   dependencies:
-    chalk "^1.1.3"
-    concat-stream "^1.4.6"
-    debug "^2.1.1"
-    doctrine "^1.2.2"
-    es6-map "^0.1.3"
-    escope "^3.6.0"
-    espree "^3.1.6"
-    estraverse "^4.2.0"
+    fast-diff "^1.1.1"
+    jest-docblock "^21.0.0"
+
+eslint-plugin-react@^7.7.0:
+  version "7.7.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160"
+  dependencies:
+    doctrine "^2.0.2"
+    has "^1.0.1"
+    jsx-ast-utils "^2.0.1"
+    prop-types "^15.6.0"
+
+eslint-scope@^3.7.1, eslint-scope@~3.7.1:
+  version "3.7.1"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-visitor-keys@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
+eslint@^4.18.1:
+  version "4.18.1"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.1.tgz#b9138440cb1e98b2f44a0d578c6ecf8eae6150b0"
+  dependencies:
+    ajv "^5.3.0"
+    babel-code-frame "^6.22.0"
+    chalk "^2.1.0"
+    concat-stream "^1.6.0"
+    cross-spawn "^5.1.0"
+    debug "^3.1.0"
+    doctrine "^2.1.0"
+    eslint-scope "^3.7.1"
+    eslint-visitor-keys "^1.0.0"
+    espree "^3.5.2"
+    esquery "^1.0.0"
     esutils "^2.0.2"
-    file-entry-cache "^1.1.1"
-    glob "^7.0.3"
-    globals "^9.2.0"
-    ignore "^3.1.2"
+    file-entry-cache "^2.0.0"
+    functional-red-black-tree "^1.0.1"
+    glob "^7.1.2"
+    globals "^11.0.1"
+    ignore "^3.3.3"
     imurmurhash "^0.1.4"
-    inquirer "^0.12.0"
-    is-my-json-valid "^2.10.0"
+    inquirer "^3.0.6"
     is-resolvable "^1.0.0"
-    js-yaml "^3.5.1"
-    json-stable-stringify "^1.0.0"
+    js-yaml "^3.9.1"
+    json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.3.0"
-    lodash "^4.0.0"
-    mkdirp "^0.5.0"
-    optionator "^0.8.1"
-    path-is-absolute "^1.0.0"
-    path-is-inside "^1.0.1"
-    pluralize "^1.2.1"
-    progress "^1.1.8"
-    require-uncached "^1.0.2"
-    shelljs "^0.6.0"
-    strip-json-comments "~1.0.1"
-    table "^3.7.8"
+    lodash "^4.17.4"
+    minimatch "^3.0.2"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.2"
+    pluralize "^7.0.0"
+    progress "^2.0.0"
+    require-uncached "^1.0.3"
+    semver "^5.3.0"
+    strip-ansi "^4.0.0"
+    strip-json-comments "~2.0.1"
+    table "^4.0.1"
     text-table "~0.2.0"
-    user-home "^2.0.0"
-
-espree@^2.0.1:
-  version "2.2.5"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-2.2.5.tgz#df691b9310889402aeb29cc066708c56690b854b"
 
-espree@^3.1.6:
-  version "3.5.2"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
+espree@^3.5.2:
+  version "3.5.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.3.tgz#931e0af64e7fbbed26b050a29daad1fc64799fa6"
   dependencies:
-    acorn "^5.2.1"
+    acorn "^5.4.0"
     acorn-jsx "^3.0.0"
 
 esprima-fb@^15001.1.0-dev-harmony-fb:
@@ -3966,6 +4121,12 @@ esprima@^4.0.0, esprima@~4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
 
+esquery@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+  dependencies:
+    estraverse "^4.0.0"
+
 esrecurse@^4.1.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
@@ -3973,7 +4134,7 @@ esrecurse@^4.1.0:
     estraverse "^4.1.0"
     object-assign "^4.0.1"
 
-estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
 
@@ -4039,10 +4200,6 @@ exenv@^1.2.0, exenv@^1.2.1:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
 
-exit-hook@^1.0.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
-
 exit@0.1.2, exit@0.1.x:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@@ -4146,6 +4303,14 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
 
+external-editor@^2.0.4:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48"
+  dependencies:
+    chardet "^0.4.0"
+    iconv-lite "^0.4.17"
+    tmp "^0.0.33"
+
 extglob@^0.3.1:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
@@ -4189,6 +4354,10 @@ fast-deep-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
 
+fast-diff@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
+
 fast-json-stable-stringify@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
@@ -4235,16 +4404,15 @@ fbjs@^0.8.12, fbjs@^0.8.16, fbjs@^0.8.9:
     setimmediate "^1.0.5"
     ua-parser-js "^0.7.9"
 
-figures@^1.3.5:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
   dependencies:
     escape-string-regexp "^1.0.5"
-    object-assign "^4.1.0"
 
-file-entry-cache@^1.1.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8"
+file-entry-cache@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
   dependencies:
     flat-cache "^1.2.1"
     object-assign "^4.0.1"
@@ -4510,6 +4678,10 @@ function.prototype.name@^1.0.0, function.prototype.name@^1.1.0:
     function-bind "^1.1.1"
     is-callable "^1.1.3"
 
+functional-red-black-tree@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+
 fuse.js@^2.2.0:
   version "2.7.4"
   resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9"
@@ -4565,6 +4737,10 @@ get-stdin@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
 
+get-stdin@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
+
 get-stream@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@@ -4717,7 +4893,11 @@ global@^4.3.0, global@^4.3.2:
     min-document "^2.19.0"
     process "~0.5.1"
 
-globals@^9.18.0, globals@^9.2.0:
+globals@^11.0.1, globals@^11.1.0:
+  version "11.3.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0"
+
+globals@^9.18.0:
   version "9.18.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
 
@@ -4967,6 +5147,10 @@ has-flag@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
 
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+
 has-gulplog@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce"
@@ -5215,6 +5399,10 @@ http-errors@1.6.2, http-errors@~1.6.2:
     setprototypeof "1.0.3"
     statuses ">= 1.3.1 < 2"
 
+http-loader@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/http-loader/-/http-loader-0.0.1.tgz#b04f8c2d8e872ae079572606eff0f4b8ef55d07c"
+
 http-parser-js@>=0.4.0:
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1"
@@ -5267,7 +5455,7 @@ i@0.3.x:
   version "0.3.6"
   resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d"
 
-iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
+iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
   version "0.4.19"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
 
@@ -5293,7 +5481,7 @@ ignore-loader@^0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463"
 
-ignore@^3.1.2:
+ignore@^3.3.3:
   version "3.3.7"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
 
@@ -5371,22 +5559,23 @@ inline-style-prefixer@^3.0.6:
     bowser "^1.7.3"
     css-in-js-utils "^2.0.0"
 
-inquirer@^0.12.0:
-  version "0.12.0"
-  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
+inquirer@^3.0.6:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
   dependencies:
-    ansi-escapes "^1.1.0"
-    ansi-regex "^2.0.0"
-    chalk "^1.0.0"
-    cli-cursor "^1.0.1"
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.0"
+    cli-cursor "^2.1.0"
     cli-width "^2.0.0"
-    figures "^1.3.5"
+    external-editor "^2.0.4"
+    figures "^2.0.0"
     lodash "^4.3.0"
-    readline2 "^1.0.1"
-    run-async "^0.1.0"
-    rx-lite "^3.1.2"
-    string-width "^1.0.1"
-    strip-ansi "^3.0.0"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rx-lite "^4.0.8"
+    rx-lite-aggregates "^4.0.8"
+    string-width "^2.1.0"
+    strip-ansi "^4.0.0"
     through "^2.3.6"
 
 insert-css@^1.0.0:
@@ -5437,6 +5626,12 @@ invariant@2.x.x, invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.1, invariant
   dependencies:
     loose-envify "^1.0.0"
 
+invariant@^2.2.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688"
+  dependencies:
+    loose-envify "^1.0.0"
+
 invert-kv@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
@@ -5608,7 +5803,7 @@ is-glob@^4.0.0:
   dependencies:
     is-extglob "^2.1.1"
 
-is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
+is-my-json-valid@^2.12.4:
   version "2.17.1"
   resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
   dependencies:
@@ -5673,6 +5868,10 @@ is-primitive@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
 
+is-promise@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
 is-property@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
@@ -5905,7 +6104,7 @@ jest-diff@^21.2.1:
     jest-get-type "^21.2.0"
     pretty-format "^21.2.1"
 
-jest-docblock@^21.2.0:
+jest-docblock@^21.0.0, jest-docblock@^21.2.0:
   version "21.2.0"
   resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
 
@@ -6073,7 +6272,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
 
-js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0:
+js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1:
   version "3.10.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
   dependencies:
@@ -6119,6 +6318,10 @@ jsesc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
 
+jsesc@^2.5.1:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe"
+
 jsesc@~0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
@@ -6148,7 +6351,11 @@ json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
 
-json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+
+json-stable-stringify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
   dependencies:
@@ -6193,6 +6400,12 @@ jstransform@11:
     object-assign "^2.0.0"
     source-map "^0.4.2"
 
+jsx-ast-utils@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f"
+  dependencies:
+    array-includes "^3.0.3"
+
 jsx-loader@^0.13.2:
   version "0.13.2"
   resolved "https://registry.yarnpkg.com/jsx-loader/-/jsx-loader-0.13.2.tgz#9767f643975c78f5e5abeba9bc57885297e732d4"
@@ -7019,11 +7232,7 @@ multipipe@^0.1.0, multipipe@^0.1.2:
   dependencies:
     duplexer2 "0.0.2"
 
-mute-stream@0.0.5:
-  version "0.0.5"
-  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
-
-mute-stream@~0.0.4:
+mute-stream@0.0.7, mute-stream@~0.0.4:
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
 
@@ -7432,9 +7641,11 @@ once@~1.3.0:
   dependencies:
     wrappy "1"
 
-onetime@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  dependencies:
+    mimic-fn "^1.0.0"
 
 opn@^5.1.0:
   version "5.2.0"
@@ -7449,7 +7660,7 @@ optimist@^0.6.1, optimist@~0.6.0:
     minimist "~0.0.1"
     wordwrap "~0.0.2"
 
-optionator@^0.8.1:
+optionator@^0.8.1, optionator@^0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   dependencies:
@@ -7504,7 +7715,7 @@ os-locale@^2.0.0:
     lcid "^1.0.0"
     mem "^1.1.0"
 
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
 
@@ -7636,7 +7847,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
 
-path-is-inside@^1.0.1:
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
 
@@ -7755,9 +7966,9 @@ plugin-error@^1.0.0:
     arr-union "^3.1.0"
     extend-shallow "^3.0.2"
 
-pluralize@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
+pluralize@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
 
 podda@^1.2.1, podda@^1.2.2:
   version "1.2.2"
@@ -8089,6 +8300,10 @@ preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
 
+prettier@^1.10.2:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.2.tgz#1af8356d1842276a99a5b5529c82dd9e9ad3cc93"
+
 pretty-error@^2.0.2:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
@@ -8123,9 +8338,9 @@ process@~0.5.1:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
 
-progress@^1.1.8:
-  version "1.1.8"
-  resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
+progress@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
 
 promise-inflight@^1.0.1:
   version "1.0.1"
@@ -8417,6 +8632,15 @@ react-dom-factories@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.2.tgz#eb7705c4db36fb501b3aa38ff759616aa0ff96e0"
 
+react-dom@15.6.2, react-dom@^15.6.2:
+  version "15.6.2"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730"
+  dependencies:
+    fbjs "^0.8.9"
+    loose-envify "^1.1.0"
+    object-assign "^4.1.0"
+    prop-types "^15.5.10"
+
 react-dom@16.x.x:
   version "16.2.0"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
@@ -8426,15 +8650,6 @@ react-dom@16.x.x:
     object-assign "^4.1.1"
     prop-types "^15.6.0"
 
-react-dom@^15.5.4, react-dom@^15.6.2:
-  version "15.6.2"
-  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730"
-  dependencies:
-    fbjs "^0.8.9"
-    loose-envify "^1.1.0"
-    object-assign "^4.1.0"
-    prop-types "^15.5.10"
-
 react-dropzone@4.2.3:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-4.2.3.tgz#f7bc92aa5fe4253fdb1fd3792114d2d29b47119a"
@@ -8681,16 +8896,7 @@ react-truncate@^2.0.5:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/react-truncate/-/react-truncate-2.3.0.tgz#d469b355aff1f83ae9e0f2fed0d47dfd061e5d2e"
 
-react@16.x.x:
-  version "16.2.0"
-  resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
-  dependencies:
-    fbjs "^0.8.16"
-    loose-envify "^1.1.0"
-    object-assign "^4.1.1"
-    prop-types "^15.6.0"
-
-react@^15.4.1, react@^15.5.4, react@^15.6.2:
+react@15.6.2, react@^15.4.1, react@^15.6.2:
   version "15.6.2"
   resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72"
   dependencies:
@@ -8700,6 +8906,15 @@ react@^15.4.1, react@^15.5.4, react@^15.6.2:
     object-assign "^4.1.0"
     prop-types "^15.5.10"
 
+react@16.x.x:
+  version "16.2.0"
+  resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
+  dependencies:
+    fbjs "^0.8.16"
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.0"
+
 reactcss@^1.2.0:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
@@ -8790,14 +9005,6 @@ readdirp@^2.0.0:
     readable-stream "^2.0.2"
     set-immediate-shim "^1.0.1"
 
-readline2@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
-  dependencies:
-    code-point-at "^1.0.0"
-    is-fullwidth-code-point "^1.0.0"
-    mute-stream "0.0.5"
-
 recast@^0.11.17, recast@~0.11.12:
   version "0.11.23"
   resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
@@ -9063,7 +9270,7 @@ require-main-filename@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
 
-require-uncached@^1.0.2:
+require-uncached@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
   dependencies:
@@ -9103,18 +9310,18 @@ resolve@1.1.7:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
 
-resolve@^1.1.6, resolve@^1.1.7:
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
   dependencies:
     path-parse "^1.0.5"
 
-restore-cursor@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
   dependencies:
-    exit-hook "^1.0.0"
-    onetime "^1.0.0"
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
 
 revalidator@0.1.x:
   version "0.1.8"
@@ -9147,11 +9354,11 @@ rosie@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/rosie/-/rosie-1.6.0.tgz#bc0ef64cd401d00794450d5792c0276e226b6ab0"
 
-run-async@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+run-async@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
   dependencies:
-    once "^1.3.0"
+    is-promise "^2.1.0"
 
 run-queue@^1.0.0, run-queue@^1.0.3:
   version "1.0.3"
@@ -9171,17 +9378,23 @@ rw@1:
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
 
-rx-lite@^3.1.2:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+rx-lite-aggregates@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
+  dependencies:
+    rx-lite "*"
+
+rx-lite@*, rx-lite@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
 
 rx@4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
 
-rxjs@5.0.0-beta.12:
-  version "5.0.0-beta.12"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.0.0-beta.12.tgz#cdfde2d8c4639d20ae7794bff8fddf32da7ad337"
+rxjs@5.4.2:
+  version "5.4.2"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.2.tgz#2a3236fcbf03df57bae06fd6972fd99e5c08fcf7"
   dependencies:
     symbol-observable "^1.0.1"
 
@@ -9246,22 +9459,27 @@ scss-tokenizer@^0.2.3:
     js-base64 "^2.1.8"
     source-map "^0.4.2"
 
-sdc-ui@1.6.9:
-  version "1.6.9"
-  resolved "https://registry.yarnpkg.com/sdc-ui/-/sdc-ui-1.6.9.tgz#cfb85152b1ff4890e869b0903527462d562a8e68"
+sdc-ui@1.6.24:
+  version "1.6.24"
+  resolved "https://registry.yarnpkg.com/sdc-ui/-/sdc-ui-1.6.24.tgz#059b0fe6fdc36c962b65853a8012885aa38e78a7"
   dependencies:
-    "@angular/common" "2.3.1"
-    "@angular/core" "2.3.1"
-    "@angular/platform-browser" "2.3.1"
-    "@angular/platform-browser-dynamic" "2.3.1"
+    "@angular/common" "~2.4.8"
+    "@angular/core" "~2.4.8"
+    "@angular/forms" "~2.4.8"
+    "@angular/http" "^2.4.8"
+    "@angular/platform-browser" "~2.4.8"
+    "@angular/platform-browser-dynamic" "~2.4.8"
     "@angular/router" "~3.2.1"
+    "@angular/upgrade" "^2.4.8"
     "@storybook/react" "^3.1.5"
-    react "^15.5.4"
-    react-dom "^15.5.4"
+    http-loader "0.0.1"
+    prop-types "^15.6.0"
+    react "15.6.2"
+    react-dom "15.6.2"
     reflect-metadata "^0.1.3"
-    rxjs "5.0.0-beta.12"
+    rxjs "5.4.2"
     svg-react-loader "^0.4.4"
-    zone.js "~0.6.26"
+    zone.js "^0.8.18"
 
 select-hose@^2.0.0:
   version "2.0.0"
@@ -9426,10 +9644,6 @@ shelljs@0.3.x:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1"
 
-shelljs@^0.6.0:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
-
 shelljs@^0.7.4, shelljs@^0.7.8:
   version "0.7.8"
   resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
@@ -9454,9 +9668,11 @@ slash@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
 
-slice-ansi@0.0.4:
-  version "0.0.4"
-  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+slice-ansi@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
 
 slide@^1.1.5:
   version "1.1.6"
@@ -9582,7 +9798,7 @@ source-map@0.5.6:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
 
-source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.6:
+source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
 
@@ -9768,7 +9984,7 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
 
-string-width@^2.0.0:
+string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
   dependencies:
@@ -9850,7 +10066,7 @@ strip-indent@^1.0.1:
   dependencies:
     get-stdin "^4.0.1"
 
-strip-json-comments@1.0.x, strip-json-comments@~1.0.1:
+strip-json-comments@1.0.x:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
 
@@ -9903,6 +10119,12 @@ supports-color@^5.1.0:
   dependencies:
     has-flag "^2.0.0"
 
+supports-color@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
+  dependencies:
+    has-flag "^3.0.0"
+
 svg-react-loader@^0.4.4:
   version "0.4.5"
   resolved "https://registry.yarnpkg.com/svg-react-loader/-/svg-react-loader-0.4.5.tgz#1f324c9c7b858f5c89fac752bbe9ca3f6214f850"
@@ -9948,16 +10170,16 @@ symbol-tree@^3.2.1:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
 
-table@^3.7.8:
-  version "3.8.3"
-  resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
+table@^4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
   dependencies:
-    ajv "^4.7.0"
-    ajv-keywords "^1.0.0"
-    chalk "^1.1.1"
-    lodash "^4.0.0"
-    slice-ansi "0.0.4"
-    string-width "^2.0.0"
+    ajv "^6.0.1"
+    ajv-keywords "^3.0.0"
+    chalk "^2.1.0"
+    lodash "^4.17.4"
+    slice-ansi "1.0.0"
+    string-width "^2.1.1"
 
 tapable@^0.1.8, tapable@~0.1.8:
   version "0.1.10"
@@ -10074,6 +10296,12 @@ tinycolor2@^1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
 
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  dependencies:
+    os-tmpdir "~1.0.2"
+
 tmpl@1.0.x:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
@@ -10086,6 +10314,10 @@ to-fast-properties@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
 
+to-fast-properties@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
 to-object-path@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
@@ -10361,12 +10593,6 @@ user-home@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
 
-user-home@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
-  dependencies:
-    os-homedir "^1.0.0"
-
 util-deprecate@^1.0.2, util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -10986,6 +11212,6 @@ yazl@^2.1.0:
   dependencies:
     buffer-crc32 "~0.2.3"
 
-zone.js@~0.6.26:
-  version "0.6.26"
-  resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.6.26.tgz#067c13b8b80223a89b62e9dc82680f09762c4636"
+zone.js@^0.8.18:
+  version "0.8.20"
+  resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.20.tgz#a218c48db09464b19ff6fc8f0d4bb5b1046e185d"