diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/themes/default/default-theme.css b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/themes/default/default-theme.css
index 3aef9f7675..9792737464 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/themes/default/default-theme.css
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/themes/default/default-theme.css
@@ -211,6 +211,10 @@ body {
height: 300px;
}
+#form-error {
+ color: red;
+}
+
.application-create-banner-dropzone {
width: 300px;
height: 150px;
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/common/validator.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/common/validator.js
new file mode 100644
index 0000000000..11654012f0
--- /dev/null
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/common/validator.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you 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.
+ */
+
+'use strict';
+
+/**
+ * This Utility class will contain basic methods for form validation.
+ * */
+export const validateURL = (value) => {
+
+};
+
+export const validateNull = (value) => {
+ return !value;
+};
+
+export const validateEmpty = (array) => {
+ return array.length > 0;
+};
+
+export const validateEmptyObject = (object) => {
+ return Object.keys(object).length > 0;
+};
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/ApplicationCreate.jsx b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/ApplicationCreate.jsx
index 38620bf8f2..42112f1125 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/ApplicationCreate.jsx
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/ApplicationCreate.jsx
@@ -126,7 +126,7 @@ class ApplicationCreate extends Component {
* @param data: The form data of the step.
* */
setStepData(step, data) {
- console.log(step, data, this.state.stepData); //TODO: Remove this
+ console.log(step, data, this.state); //TODO: Remove this
switch (step) {
case "generalInfo": {
this.setState({generalInfo: data}, this.onNextClick());
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step1.jsx b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step1.jsx
index 9f011fdf67..bffa63b599 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step1.jsx
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step1.jsx
@@ -18,9 +18,9 @@
import PropTypes from 'prop-types';
import React, {Component} from 'react';
-import {Badge, FormGroup, Input, Label} from 'reactstrap';
import {FormattedMessage} from 'react-intl';
-import {Badge, Button, Form, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
+import {Badge, Button, Form, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
+import * as validator from '../../../../common/validator';
/**
* The Second step of application create wizard.
@@ -49,6 +49,7 @@ class Step1 extends Component {
this.onVisibilityChange = this.onVisibilityChange.bind(this);
this.onVisibilityItemSelect = this.onVisibilityItemSelect.bind(this);
this.handleRequestDelete = this.handleRequestDelete.bind(this);
+ this.validate = this.validate.bind(this);
this.state = {
tags: [],
name: "",
@@ -63,7 +64,7 @@ class Step1 extends Component {
componentWillMount() {
const defaultVals = this.props.defaultData;
- if(defaultVals) {
+ if (defaultVals) {
this.setState(defaultVals);
}
@@ -114,19 +115,49 @@ class Step1 extends Component {
tags: tags,
visibility: visibility
};
- this.props.setStepData("generalInfo", stepData);
+
+ let {errorCount, errors} = this.validate();
+
+ if (errorCount !== 0) {
+ this.setState({errors: errors});
+ } else {
+ this.props.setStepData("generalInfo", stepData);
+ }
};
onCancelClick() {
this.props.close();
}
+ /**
+ * Validate the form fields.
+ * */
+ validate() {
+ const {name, description, tags} = this.state;
+ let errorCount = 0;
+ let errors = {};
+ if (validator.validateNull(name)) {
+ errorCount++;
+ errors.name = "Application Title is Required!";
+ }
+
+ if (validator.validateNull(description)) {
+ errorCount++;
+ errors.description = "Description is Required!"
+ }
+
+ if (!validator.validateEmpty(tags)) {
+ errorCount++;
+ errors.tags = "You need to enter at least one tag!"
+ }
+ return {errorCount, errors};
+ }
+
/**
* Set text field values to state.
* */
onTextFieldChange(event) {
let field = event.target.name;
- console.log(field, event.target.value);
switch (field) {
case "appName": {
this.setState({name: event.target.value});
@@ -166,7 +197,7 @@ class Step1 extends Component {
onChange={this.onVisibilityItemSelect}
>
-
+
@@ -192,7 +223,7 @@ class Step1 extends Component {
};
return (
-
+
@@ -207,6 +238,7 @@ class Step1 extends Component {
value={this.state.name}
onChange={this.onTextFieldChange}
/>
+ {this.state.errors.name}
@@ -293,8 +329,7 @@ class Step1 extends Component {
Step1.prototypes = {
handleNext: PropTypes.func,
handlePrev: PropTypes.func,
- setData: PropTypes.func,
- removeData: PropTypes.func
+ setData: PropTypes.func
};
export default Step1;
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step2.jsx b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step2.jsx
index 3143b2eb85..d6d627cee0 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step2.jsx
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step2.jsx
@@ -20,8 +20,9 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react';
import AuthHandler from "../../../../api/authHandler";
import PlatformMgtApi from "../../../../api/platformMgtApi";
-import {Button, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
+import {Button, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
import {FormattedMessage} from 'react-intl';
+import * as validator from '../../../../common/validator';
/**
* The first step of the application creation wizard.
@@ -43,11 +44,13 @@ class Step2 extends Component {
this.setStepData = this.setStepData.bind(this);
this.onCancelClick = this.onCancelClick.bind(this);
this.onBackClick = this.onBackClick.bind(this);
+ this.validate = this.validate.bind(this);
this.platforms = [];
this.state = {
+ errors: {},
store: 1,
platformSelectedIndex: 0,
- platform: "",
+ platform: {},
platforms: []
};
}
@@ -80,7 +83,7 @@ class Step2 extends Component {
platform = platforms[index];
tmpPlatforms.push(platform);
}
- this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
+ this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0})
}
/**
@@ -92,7 +95,14 @@ class Step2 extends Component {
store: store,
platform: platform[0]
};
- this.props.setStepData("platform", data);
+
+ const {errorCount, errors} = this.validate();
+
+ if (errorCount > 0) {
+ this.setState({errors: errors})
+ } else {
+ this.props.setStepData("platform", data);
+ }
}
onCancelClick() {
@@ -103,6 +113,17 @@ class Step2 extends Component {
this.props.handlePrev();
}
+ validate() {
+ const {store, platform} = this.state;
+ let errors = {};
+ let errorCount = 0;
+ if (!validator.validateEmptyObject(platform)) {
+ errorCount++;
+ errors.platform = "You must select an application platform!"
+ }
+ return {errorCount, errors};
+ }
+
/**
* Triggers when changing the Platform selection.
* */
@@ -149,6 +170,7 @@ class Step2 extends Component {
)
}) :
}
+
{this.state.errors.platform}
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step3.jsx b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step3.jsx
index 61b14509d3..76384d2214 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step3.jsx
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/src/components/Application/Create/CreateSteps/Step3.jsx
@@ -19,7 +19,8 @@
import PropTypes from 'prop-types';
import Dropzone from 'react-dropzone';
import React, {Component} from 'react';
-import {Button, FormGroup, Label, ModalFooter} from 'reactstrap';
+import * as validator from '../../../../common/validator';
+import {Button, FormFeedback, FormGroup, Label, ModalFooter} from 'reactstrap';
import AppImage from "../../../UIComponents/AppImage/AppImage";
import {FormattedMessage} from 'react-intl';
@@ -42,6 +43,7 @@ class Step3 extends Component {
super();
this.setStepData = this.setStepData.bind(this);
this.onBackClick = this.onBackClick.bind(this);
+ this.validate = this.validate.bind(this);
this.onCancelClick = this.onCancelClick.bind(this);
this.state = {
icon: [],
@@ -57,18 +59,6 @@ class Step3 extends Component {
this.setState(defaultData);
}
- /**
- * Handles Chip delete function.
- * Removes the tag from state.tags
- * */
- handleRequestDelete(event) {
- this.chipData = this.state.tags;
- console.log(event.target); //TODO: Remove Console log.
- const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
- this.chipData.splice(chipToDelete, 1);
- this.setState({tags: this.chipData});
- };
-
/**
* Creates an object with the current step data and persist in the parent.
* */
@@ -82,7 +72,14 @@ class Step3 extends Component {
screenshots: screenshots
};
- this.props.setStepData("screenshots", stepData);
+ const {errorCount, errors} = this.validate();
+
+ if (errorCount > 0) {
+ this.setState({errors: errors})
+ } else {
+ this.props.setStepData("screenshots", stepData);
+ }
+
};
onCancelClick() {
@@ -93,6 +90,28 @@ class Step3 extends Component {
this.props.handlePrev();
}
+ validate() {
+ const {icon, banner, screenshots} = this.state;
+ let errors = {}, errorCount = 0;
+
+ if (!validator.validateEmpty(icon)) {
+ errorCount++;
+ errors.icon = "You must upload an icon image!"
+ }
+
+ if (!validator.validateEmpty(banner)) {
+ errorCount++;
+ errors.banner = "You must upload a banner image!"
+ }
+
+ if (!validator.validateEmpty(screenshots)) {
+ errorCount++;
+ errors.screenshots = "You must upload at least one screenshot image!"
+ }
+
+ return {errorCount, errors};
+ }
+
/**
* Removed user uploaded banner.
* */
@@ -146,6 +165,7 @@ class Step3 extends Component {
: }
+
{this.state.errors.screenshots}
@@ -173,6 +193,7 @@ class Step3 extends Component {
:
}
+ {this.state.errors.icon}
@@ -199,6 +220,7 @@ class Step3 extends Component {
:
}
+ {this.state.errors.banner}