Added form validations for application create.

merge-requests/7/head
Menaka Jayawardena 7 years ago
parent 7fa3c886fb
commit 34ff40ef21

@ -211,6 +211,10 @@ body {
height: 300px; height: 300px;
} }
#form-error {
color: red;
}
.application-create-banner-dropzone { .application-create-banner-dropzone {
width: 300px; width: 300px;
height: 150px; height: 150px;

@ -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;
};

@ -126,7 +126,7 @@ class ApplicationCreate extends Component {
* @param data: The form data of the step. * @param data: The form data of the step.
* */ * */
setStepData(step, data) { setStepData(step, data) {
console.log(step, data, this.state.stepData); //TODO: Remove this console.log(step, data, this.state); //TODO: Remove this
switch (step) { switch (step) {
case "generalInfo": { case "generalInfo": {
this.setState({generalInfo: data}, this.onNextClick()); this.setState({generalInfo: data}, this.onNextClick());

@ -18,9 +18,9 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Badge, FormGroup, Input, Label} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; 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. * The Second step of application create wizard.
@ -49,6 +49,7 @@ class Step1 extends Component {
this.onVisibilityChange = this.onVisibilityChange.bind(this); this.onVisibilityChange = this.onVisibilityChange.bind(this);
this.onVisibilityItemSelect = this.onVisibilityItemSelect.bind(this); this.onVisibilityItemSelect = this.onVisibilityItemSelect.bind(this);
this.handleRequestDelete = this.handleRequestDelete.bind(this); this.handleRequestDelete = this.handleRequestDelete.bind(this);
this.validate = this.validate.bind(this);
this.state = { this.state = {
tags: [], tags: [],
name: "", name: "",
@ -63,7 +64,7 @@ class Step1 extends Component {
componentWillMount() { componentWillMount() {
const defaultVals = this.props.defaultData; const defaultVals = this.props.defaultData;
if(defaultVals) { if (defaultVals) {
this.setState(defaultVals); this.setState(defaultVals);
} }
@ -114,19 +115,49 @@ class Step1 extends Component {
tags: tags, tags: tags,
visibility: visibility visibility: visibility
}; };
let {errorCount, errors} = this.validate();
if (errorCount !== 0) {
this.setState({errors: errors});
} else {
this.props.setStepData("generalInfo", stepData); this.props.setStepData("generalInfo", stepData);
}
}; };
onCancelClick() { onCancelClick() {
this.props.close(); 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. * Set text field values to state.
* */ * */
onTextFieldChange(event) { onTextFieldChange(event) {
let field = event.target.name; let field = event.target.name;
console.log(field, event.target.value);
switch (field) { switch (field) {
case "appName": { case "appName": {
this.setState({name: event.target.value}); this.setState({name: event.target.value});
@ -166,7 +197,7 @@ class Step1 extends Component {
onChange={this.onVisibilityItemSelect} onChange={this.onVisibilityItemSelect}
> >
<option id="app-visibility-default" disabled selected>Select the Roles.</option> <option id="app-visibility-default" disabled selected>Select the Roles.</option>
<option><Input type="checkbox" />Role1</option> <option><Input type="checkbox"/>Role1</option>
<option>Role2</option> <option>Role2</option>
</Input> </Input>
</FormGroup> </FormGroup>
@ -192,7 +223,7 @@ class Step1 extends Component {
}; };
return ( return (
<div className="createStep2Content"> <div>
<div> <div>
<div> <div>
<FormGroup> <FormGroup>
@ -207,6 +238,7 @@ class Step1 extends Component {
value={this.state.name} value={this.state.name}
onChange={this.onTextFieldChange} onChange={this.onTextFieldChange}
/> />
<FormFeedback id="form-error">{this.state.errors.name}</FormFeedback>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="app-description"> <Label for="app-description">
@ -220,6 +252,7 @@ class Step1 extends Component {
value={this.state.description} value={this.state.description}
onChange={this.onTextFieldChange} onChange={this.onTextFieldChange}
/> />
<FormFeedback id="form-error">{this.state.errors.description}</FormFeedback>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="app-category"> <Label for="app-category">
@ -244,7 +277,8 @@ class Step1 extends Component {
<option id="app-visibility-default" disabled selected>Select the App Visibility <option id="app-visibility-default" disabled selected>Select the App Visibility
Option. Option.
</option> </option>
<option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/></option> <option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/>
</option>
<option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option> <option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option>
<option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option> <option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option>
</Input> </Input>
@ -263,6 +297,7 @@ class Step1 extends Component {
onChange={this.handleTagChange.bind(this)} onChange={this.handleTagChange.bind(this)}
onKeyPress={this.addTags.bind(this)} onKeyPress={this.addTags.bind(this)}
/> />
<div id="batch-content"> <div id="batch-content">
{this.state.tags.map(tag => { {this.state.tags.map(tag => {
return ( return (
@ -278,6 +313,7 @@ class Step1 extends Component {
} }
)} )}
</div> </div>
<FormFeedback id="form-error">{this.state.errors.tags}</FormFeedback>
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
@ -293,8 +329,7 @@ class Step1 extends Component {
Step1.prototypes = { Step1.prototypes = {
handleNext: PropTypes.func, handleNext: PropTypes.func,
handlePrev: PropTypes.func, handlePrev: PropTypes.func,
setData: PropTypes.func, setData: PropTypes.func
removeData: PropTypes.func
}; };
export default Step1; export default Step1;

@ -20,8 +20,9 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from "../../../../api/authHandler"; import AuthHandler from "../../../../api/authHandler";
import PlatformMgtApi from "../../../../api/platformMgtApi"; 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 {FormattedMessage} from 'react-intl';
import * as validator from '../../../../common/validator';
/** /**
* The first step of the application creation wizard. * The first step of the application creation wizard.
@ -43,11 +44,13 @@ class Step2 extends Component {
this.setStepData = this.setStepData.bind(this); this.setStepData = this.setStepData.bind(this);
this.onCancelClick = this.onCancelClick.bind(this); this.onCancelClick = this.onCancelClick.bind(this);
this.onBackClick = this.onBackClick.bind(this); this.onBackClick = this.onBackClick.bind(this);
this.validate = this.validate.bind(this);
this.platforms = []; this.platforms = [];
this.state = { this.state = {
errors: {},
store: 1, store: 1,
platformSelectedIndex: 0, platformSelectedIndex: 0,
platform: "", platform: {},
platforms: [] platforms: []
}; };
} }
@ -80,7 +83,7 @@ class Step2 extends Component {
platform = platforms[index]; platform = platforms[index];
tmpPlatforms.push(platform); tmpPlatforms.push(platform);
} }
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name}) this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0})
} }
/** /**
@ -92,8 +95,15 @@ class Step2 extends Component {
store: store, store: store,
platform: platform[0] platform: platform[0]
}; };
const {errorCount, errors} = this.validate();
if (errorCount > 0) {
this.setState({errors: errors})
} else {
this.props.setStepData("platform", data); this.props.setStepData("platform", data);
} }
}
onCancelClick() { onCancelClick() {
this.props.close(); this.props.close();
@ -103,6 +113,17 @@ class Step2 extends Component {
this.props.handlePrev(); 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. * Triggers when changing the Platform selection.
* */ * */
@ -149,6 +170,7 @@ class Step2 extends Component {
) )
}) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>} }) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>}
</Input> </Input>
<FormFeedback id="form-error">{this.state.errors.platform}</FormFeedback>
</FormGroup> </FormGroup>
<ModalFooter> <ModalFooter>
<Button color="primary" onClick={this.onBackClick}>Back</Button> <Button color="primary" onClick={this.onBackClick}>Back</Button>

@ -19,7 +19,8 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; 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 AppImage from "../../../UIComponents/AppImage/AppImage";
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
@ -42,6 +43,7 @@ class Step3 extends Component {
super(); super();
this.setStepData = this.setStepData.bind(this); this.setStepData = this.setStepData.bind(this);
this.onBackClick = this.onBackClick.bind(this); this.onBackClick = this.onBackClick.bind(this);
this.validate = this.validate.bind(this);
this.onCancelClick = this.onCancelClick.bind(this); this.onCancelClick = this.onCancelClick.bind(this);
this.state = { this.state = {
icon: [], icon: [],
@ -57,18 +59,6 @@ class Step3 extends Component {
this.setState(defaultData); 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. * Creates an object with the current step data and persist in the parent.
* */ * */
@ -82,7 +72,14 @@ class Step3 extends Component {
screenshots: screenshots screenshots: screenshots
}; };
const {errorCount, errors} = this.validate();
if (errorCount > 0) {
this.setState({errors: errors})
} else {
this.props.setStepData("screenshots", stepData); this.props.setStepData("screenshots", stepData);
}
}; };
onCancelClick() { onCancelClick() {
@ -93,6 +90,28 @@ class Step3 extends Component {
this.props.handlePrev(); 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. * Removed user uploaded banner.
* */ * */
@ -146,6 +165,7 @@ class Step3 extends Component {
<i className="fw fw-add"></i> <i className="fw fw-add"></i>
</Dropzone> : <div/>} </Dropzone> : <div/>}
</div> </div>
<FormFeedback id="form-error">{this.state.errors.screenshots}</FormFeedback>
</FormGroup> </FormGroup>
</div> </div>
<div style={{display: 'flex'}}> <div style={{display: 'flex'}}>
@ -173,6 +193,7 @@ class Step3 extends Component {
<i className="fw fw-add"></i> <i className="fw fw-add"></i>
</Dropzone> : <div/>} </Dropzone> : <div/>}
</div> </div>
<FormFeedback id="form-error">{this.state.errors.icon}</FormFeedback>
</FormGroup> </FormGroup>
</div> </div>
<div style={{marginLeft: '15px'}}> <div style={{marginLeft: '15px'}}>
@ -199,6 +220,7 @@ class Step3 extends Component {
</Dropzone> : <div/> </Dropzone> : <div/>
} }
</div> </div>
<FormFeedback id="form-error">{this.state.errors.banner}</FormFeedback>
</FormGroup> </FormGroup>
</div> </div>
</div> </div>

Loading…
Cancel
Save