<commit_before>/*
 * 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.
 */

import React, {Component} from 'react'
import {Link} from 'react-router-dom'
import {Col, Popconfirm, Row, Form, Dropdown, Tag, Menu, Badge, message} from 'antd';

const FormItem = Form.Item;
import Loading from '../../Base/Loading/Loading'
import ResourceNotFound from "../../Base/Errors/ResourceNotFound";
import Api from '../../../data/api'

import {withStyles} from 'material-ui/styles';
import Paper from 'material-ui/Paper';
import Grid from 'material-ui/Grid';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import Card, {CardActions, CardContent, CardMedia} from 'material-ui/Card';
import {MenuItem} from 'material-ui/Menu';
import {Delete, Edit, CreateNewFolder, Description}from 'material-ui-icons';
import Table, {TableBody, TableCell, TableRow} from 'material-ui/Table';
import Select from 'material-ui/Select';
import 'react-select/dist/react-select.css';
import Subscriptions  from 'material-ui-icons/Subscriptions';
import {FormControl} from 'material-ui/Form';
import NotificationSystem from 'react-notification-system';
import FavoriteIcon from 'material-ui-icons/Favorite';
import ShareIcon from 'material-ui-icons/Share';
import IconButton from 'material-ui/IconButton';
import Divider from 'material-ui/Divider';
import CodeIcon from 'material-ui-icons/Code';
import EmailIcon from 'material-ui-icons/Email';

const styles = theme => ({
    media: {
        height: 200,
    },
});

class BasicInfo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            api: null,
            applications: null,
            policies: null,
            dropDownApplications: null,
            dropDownPolicies: null,
            notFound: false,
            matDropVisible: false,
            matDropValue: 'one',
            subscribedApplicationIds: [],
            options: [],
            tiers: [],
            applicationId: null,
            policyName: null
        };
        this.api_uuid = this.props.uuid;
        this.logChange = this.logChange.bind(this);
    }

    componentDidMount() {
        const api = new Api();
        let promised_api = api.getAPIById(this.api_uuid);
        promised_api.then(
            response => {
                console.info(response.obj);
                this.setState({api: response.obj});
                let apiTiers = response.obj.policies;
                let tiers = [];
                for (let i = 0; i < apiTiers.length; i++) {
                    let tierName = apiTiers[i];
                    tiers.push({value: tierName, label: tierName});
                }
                this.setState({tiers: tiers});
                if (tiers.length > 0) {
                    this.setState({policyName: tiers[0].value});
                }
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let existing_subscriptions = api.getSubscriptions(this.api_uuid, null);
        existing_subscriptions.then((response) => {
            let subscribedApplications = [];
            //get the application IDs of existing subscriptions
            response.body.list.map(element => subscribedApplications.push(element.applicationId));
            this.setState({subscribedApplicationIds: subscribedApplications});
        }).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let promised_applications = api.getAllApplications();
        promised_applications.then(
            (response) => {
                let applicationResponseObj = response.body;
                let applications = [];
                for (let i = 0; i < applicationResponseObj.list.length; i++) {
                    let applicationId = applicationResponseObj.list[i].applicationId;
                    let applicationName = applicationResponseObj.list[i].name;
                    //include the application only if it does not has an existing subscriptions
                    if (this.state.subscribedApplicationIds.includes(applicationId)) {
                        continue;
                    } else {
                        applications.push({value: applicationId, label: applicationName});
                    }
                }
                this.setState({options: applications});
                if (options.length > 0) {
                    this.setState({applicationId: options[0].value});
                }
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let promised_subscriptions = api.getSubscriptions(this.api_uuid, null);
        promised_subscriptions.then(
            response => {
                this.dropDownApplications = [<Option key="custom" onClick={this.handleClick}>New Application</Option>];

                for (var i = 0; i < this.api.policies.length; i++) {
                    this.dropDownPolicies.push(<Option key={this.api.policies[i]}>{this.api.policies[i]}</Option>);
                }
                var subscription = {};
                var subscriptions = response.obj.list;
                var application = {};
                var subscribedApp = false;
                for (var i = 0; i < this.applications.length; i++) {
                    subscribedApp = false;
                    application = applications[i];
                    if (application.lifeCycleStatus != "APPROVED") {
                        continue;
                    }
                    for (var j = 0; j < subscriptions.length; j++) {
                        subscription = subscriptions[j];
                        if (subscription.applicationId === application.applicationId) {
                            subscribedApp = true;
                            continue;
                        }
                    }
                    if (!subscribedApp) {
                        this.dropDownApplications.push(<Option key={application.id}>{application.name}</Option>);
                    }
                }
                this.policies = this.api.policies;
                console.info(this.api.policies)
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );
    }

    handleChange = name => event => {
        this.setState({[name]: event.target.value});
    };

    addNotifications() {
        this.refs.notificationSystem.addNotification( {
            message: 'Subscribe to API successfully',
            position: 'tc',
            level: 'success'
        });
    };

    createSubscription = (e) => {
        e.preventDefault();
        let apiId = this.api_uuid;
        let applicationId = this.state.applicationId;
        let policy = this.state.policyName;
        let api = new Api();
        let promised_subscribe = api.subscribe(apiId, applicationId, policy);
        promised_subscribe.then(response => {
            console.log("Subscription created successfully with ID : " + response.body.subscriptionId);
            this.addNotifications();
            let applications = this.state.options.filter(application => applicationId !== application.value );
            this.setState({options: applications});
        }).catch(error => {
                console.log("Error while creating the subscription.");
                console.error(error);
            }
        )
    };

    populateApplicationDropdown() {
        return this.dropDownApplications;
    }

    populatePolicyDropdown() {
        return this.dropDownPolicies;
    }

    handleClick() {
        this.setState({redirect: true});
    }

    selectChange() {
        this.setState({matDropVisible: !this.state.matDropVisible})
    }

    onBlur(e) {
        console.info(document.activeElement);
        if (!e.currentTarget.contains(document.activeElement)) {
            this.setState({matDropVisible: false});
        }
    }

    selectOption(option) {
        console.info(option);
        this.setState({selectOption: option});
    }

    logChange(val) {
        this.setState({matDropValue: val.value});
        console.log("Selected: " + JSON.stringify(val));
    }

    render() {
        const formItemLayout = {
            labelCol: {span: 6},
            wrapperCol: {span: 18}
        };
        if (this.state.notFound) {
            return <ResourceNotFound />
        }
        if (this.state.redirect) {
            return <Redirect push to="/application-create"/>;
        }
        const {classes} = this.props;
        const api = this.state.api;

        return (
            this.state.api ?

                    <Grid container className="tab-grid" spacing={0} >
                                {/*<Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <Edit /> Edit
                                 </Button>
                                 <Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <CreateNewFolder /> Create New Version
                                 </Button>
                                 <Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <Description /> View Swagger
                                 </Button>*/}
                        <Grid item xs={12} sm={12} md={6} lg={3} xl={2}>
                            <Card >
                                <CardMedia  className={classes.media}
                                    image="/store/public/app/images/api/api-default.png"
                                    title="API icon"
                                />
                                <CardContent>
                                    <Typography type="headline" component="h2">
                                        {api.name}
                                    </Typography>
                                    <Typography type="subheading" color="secondary">
                                        {api.version} by {api.provider}
                                    </Typography>
                                    <StarRatingBar apiIdProp={this.api_uuid}></StarRatingBar>
                                </CardContent>
                                <Divider />
                                <CardActions disableActionSpacing>
                                    <IconButton aria-label="Add to favorites">
                                        <FavoriteIcon />
                                    </IconButton>
                                    <IconButton aria-label="Share">
                                        <ShareIcon />
                                    </IconButton>
                                    <IconButton aria-label="Embed">
                                        <CodeIcon />
                                    </IconButton>
                                    <IconButton aria-label="Email">
                                        <EmailIcon />
                                    </IconButton>
                                </CardActions>
                            </Card>
                        </Grid>
                        <Grid item xs={12} sm={12} md={6} lg={4} xl={4} className="add-item-left-padding ">

                                <TableBody>
                                    <TableRow>
                                        <TableCell>
                                            Status</TableCell><TableCell><Badge status="processing" text={api.lifeCycleStatus}/></TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Context</TableCell><TableCell>{api.context}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Default API
                                            Version</TableCell><TableCell>{api.isDefaultVersion}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Date Created</TableCell><TableCell>{api.createdTime}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Date Last
                                            Updated</TableCell><TableCell>{api.lastUpdatedTime}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Rate it</TableCell>
                                        <TableCell>
                                            <StarRatingBar apiIdProp={this.api_uuid}></StarRatingBar>
                                        </TableCell>
                                    </TableRow>
                                </TableBody>

                        </Grid>
                        <Grid item xs={12}>
                            <Typography type="subheading" gutterBottom>
                                Applications
                            </Typography>
                            {this.state.options &&
                            <FormControl style={{width: "100%", marginBottom: "20px"}}>
                                <Select
                                    style={{width: "100%"}}
                                    value={this.state.applicationId}
                                    onChange={this.handleChange('applicationId')}
                                >
                                    {this.state.options.map((option) => <MenuItem key={option.value}
                                                                                value={option.value}>{option.label}</MenuItem>)}
                                </Select>
                            </FormControl>
                            }
                            <Typography type="subheading" gutterBottom>
                                Tiers
                            </Typography>
                            {this.state.tiers &&
                            <FormControl style={{width: "100%"}}>`
                                <Select
                                    style={{width: "100%"}}
                                    value={this.state.policyName}
                                    onChange={this.handleChange('policyName')}
                                >
                                    {this.state.tiers.map((tier) => <MenuItem key={tier.value}
                                                                              value={tier.value}>{tier.label}</MenuItem>)}
                                </Select>
                            </FormControl>
                            }

                            <Button onClick={this.createSubscription} raised color="primary"
                                    style={{paddingTop: '20px'}}>
                                <NotificationSystem ref="notificationSystem"/>
                                <Subscriptions style={{paddingRight: '10px'}}/> Subscribe
                            </Button>

                            {/*<Select>
                             {this.populateApplicationDropdown()}
                             </Select>
                             <Select>
                             {this.populatePolicyDropdown()}
                             </Select>*/}

                        </Grid>
                    </Grid>

                : <Loading/>
        );
    }
}

class Star extends React.Component {
    constructor(props) {
        super(props);

        this.handleHoveringOver = this.handleHoveringOver.bind(this);
    }

    handleHoveringOver(event) {
        this.props.hoverOver(this.props.name);
    }

    render() {
        return this.props.isRated ?

                ★
             :

                ☆
            ;
    }
}

class StarRatingBar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            previousRating: 0,
            rating: 0
        };

        this.handleMouseOver = this.handleMouseOver.bind(this);
        this.handleRatingUpdate = this.handleRatingUpdate.bind(this);
        this.handleMouseOut = this.handleMouseOut.bind(this);
    }

    componentDidMount() {
        var api = new Api();
        let promised_api = api.getAPIById(this.props.apiIdProp);
        promised_api.then(
            response => {
            }
        );

        //get user rating
        let promised_rating = api.getRatingFromUser(this.props.apiIdProp, null);
        promised_rating.then(
            response => {
                this.setState({rating: response.obj.userRating});
                this.setState({previousRating: response.obj.userRating});
            }
        );
    }

    handleMouseOver(index) {
        this.setState({rating: index});
    }

    handleMouseOut() {
        this.setState({rating: this.state.previousRating});
    }

    handleRatingUpdate() {
        this.setState({previousRating: this.state.rating});
        this.setState({rating: this.state.rating});

        var api = new Api();
        let ratingInfo = {"rating": this.state.rating};
        let promise = api.addRating(this.props.apiIdProp, ratingInfo);
        promise.then(
            response => {
                message.success("Rating updated successfully");
            }).catch(
            error => {
                message.error("Error occurred while adding ratings!");
            }
        );
    }

    render() {
        return (

            <Star name={1} isRated={this.state.rating >= 1} hoverOver={this.handleMouseOver}> </Star>
            <Star name={2} isRated={this.state.rating >= 2} hoverOver={this.handleMouseOver}> </Star>
            <Star name={3} isRated={this.state.rating >= 3} hoverOver={this.handleMouseOver}> </Star>
            <Star name={4} isRated={this.state.rating >= 4} hoverOver={this.handleMouseOver}> </Star>
            <Star name={5} isRated={this.state.rating >= 5} hoverOver={this.handleMouseOver}> </Star>

);
    }
}

export default withStyles(styles)(BasicInfo);
<commit_msg>Fix https://github.com/wso2/product-apim/issues/2460<commit_after>/*
 * 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.
 */

import React, {Component} from 'react'
import {Link} from 'react-router-dom'
import {Col, Popconfirm, Row, Form, Dropdown, Tag, Menu, Badge, message} from 'antd';

const FormItem = Form.Item;
import Loading from '../../Base/Loading/Loading'
import ResourceNotFound from "../../Base/Errors/ResourceNotFound";
import Api from '../../../data/api'

import {withStyles} from 'material-ui/styles';
import Paper from 'material-ui/Paper';
import Grid from 'material-ui/Grid';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import Dialog, {DialogActions, DialogContent, DialogContentText, DialogTitle} from 'material-ui/Dialog';
import Card, {CardActions, CardContent, CardMedia} from 'material-ui/Card';
import {MenuItem} from 'material-ui/Menu';
import Table, {TableBody, TableCell, TableRow} from 'material-ui/Table';
import Select from 'material-ui/Select';
import 'react-select/dist/react-select.css';
import {FormControl} from 'material-ui/Form';
import NotificationSystem from 'react-notification-system';
import FavoriteIcon from 'material-ui-icons/Favorite';
import ShareIcon from 'material-ui-icons/Share';
import IconButton from 'material-ui/IconButton';
import Divider from 'material-ui/Divider';
import CodeIcon from 'material-ui-icons/Code';
import Input, {InputLabel} from 'material-ui/Input';
import EmailIcon from 'material-ui-icons/Email';
import Slide from "material-ui/transitions/Slide";

const styles = theme => ({
    media: {
        height: 200,
    },
});

class BasicInfo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            api: null,
            applications: null,
            policies: null,
            dropDownApplications: null,
            dropDownPolicies: null,
            notFound: false,
            openSubscribeMenu: false,
            matDropVisible: false,
            matDropValue: 'one',
            subscribedApplicationIds: [],
            options: [],
            tiers: [],
            applicationId: null,
            policyName: null,
        };
        this.api_uuid = this.props.uuid;
        this.logChange = this.logChange.bind(this);
        this.openSubscribeMenu = this.openSubscribeMenu.bind(this);
        this.closeSubscribeMenu = this.closeSubscribeMenu.bind(this);
    }

    componentDidMount() {
        const api = new Api();
        let promised_api = api.getAPIById(this.api_uuid);
        promised_api.then(
            response => {
                console.info(response.obj);
                this.setState({api: response.obj});
                let apiTiers = response.obj.policies;
                let tiers = [];
                for (let i = 0; i < apiTiers.length; i++) {
                    let tierName = apiTiers[i];
                    tiers.push({value: tierName, label: tierName});
                }
                this.setState({tiers: tiers});
                if (tiers.length > 0) {
                    this.setState({policyName: tiers[0].value});
                }
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let existing_subscriptions = api.getSubscriptions(this.api_uuid, null);
        existing_subscriptions.then((response) => {
            let subscribedApplications = [];
            //get the application IDs of existing subscriptions
            response.body.list.map(element => subscribedApplications.push(element.applicationId));
            this.setState({subscribedApplicationIds: subscribedApplications});
        }).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let promised_applications = api.getAllApplications();
        promised_applications.then(
            (response) => {
                let applicationResponseObj = response.body;
                let applications = [];
                for (let i = 0; i < applicationResponseObj.list.length; i++) {
                    let applicationId = applicationResponseObj.list[i].applicationId;
                    let applicationName = applicationResponseObj.list[i].name;
                    //include the application only if it does not has an existing subscriptions
                    if (this.state.subscribedApplicationIds.includes(applicationId)) {
                        continue;
                    } else {
                        applications.push({value: applicationId, label: applicationName});
                    }
                }
                this.setState({options: applications});
                if (options.length > 0) {
                    this.setState({applicationId: options[0].value});
                }
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );

        let promised_subscriptions = api.getSubscriptions(this.api_uuid, null);
        promised_subscriptions.then(
            response => {
                this.dropDownApplications = [<Option key="custom" onClick={this.handleClick}>New Application</Option>];

                for (var i = 0; i < this.api.policies.length; i++) {
                    this.dropDownPolicies.push(<Option key={this.api.policies[i]}>{this.api.policies[i]}</Option>);
                }
                var subscription = {};
                var subscriptions = response.obj.list;
                var application = {};
                var subscribedApp = false;
                for (var i = 0; i < this.applications.length; i++) {
                    subscribedApp = false;
                    application = applications[i];
                    if (application.lifeCycleStatus != "APPROVED") {
                        continue;
                    }
                    for (var j = 0; j < subscriptions.length; j++) {
                        subscription = subscriptions[j];
                        if (subscription.applicationId === application.applicationId) {
                            subscribedApp = true;
                            continue;
                        }
                    }
                    if (!subscribedApp) {
                        this.dropDownApplications.push(<Option key={application.id}>{application.name}</Option>);
                    }
                }
                this.policies = this.api.policies;
                console.info(this.api.policies)
            }
        ).catch(
            error => {
                if (process.env.NODE_ENV !== "production") {
                    console.log(error);
                }
                let status = error.status;
                if (status === 404) {
                    this.setState({notFound: true});
                }
            }
        );
    }

    handleChange = name => event => {
        this.setState({[name]: event.target.value});
    };

    addNotifications() {
        this.refs.notificationSystem.addNotification({
            message: 'Subscribe to API successfully',
            position: 'tc',
            level: 'success'
        });
    };

    createSubscription = (e) => {
        e.preventDefault();
        let apiId = this.api_uuid;
        let applicationId = this.state.applicationId;
        let policy = this.state.policyName;
        let api = new Api();
        let promised_subscribe = api.subscribe(apiId, applicationId, policy);
        promised_subscribe.then(response => {
            console.log("Subscription created successfully with ID : " + response.body.subscriptionId);
            this.addNotifications();
            let applications = this.state.options.filter(application => applicationId !== application.value);
            this.setState({options: applications, openSubscribeMenu: false});
        }).catch(error => {
                console.log("Error while creating the subscription.");
                console.error(error);
            }
        )
    };

    populateApplicationDropdown() {
        return this.dropDownApplications;
    }

    populatePolicyDropdown() {
        return this.dropDownPolicies;
    }

    handleClick() {
        this.setState({redirect: true});
    }

    openSubscribeMenu() {
        this.setState({openSubscribeMenu: true});
    }

    closeSubscribeMenu() {
        this.setState({openSubscribeMenu: false});
    }

    selectChange() {
        this.setState({matDropVisible: !this.state.matDropVisible})
    }

    onBlur(e) {
        console.info(document.activeElement);
        if (!e.currentTarget.contains(document.activeElement)) {
            this.setState({matDropVisible: false});
        }
    }

    selectOption(option) {
        console.info(option);
        this.setState({selectOption: option});
    }

    logChange(val) {
        this.setState({matDropValue: val.value});
        console.log("Selected: " + JSON.stringify(val));
    }

    render() {
        const formItemLayout = {
            labelCol: {span: 6},
            wrapperCol: {span: 18}
        };
        if (this.state.notFound) {
            return <ResourceNotFound/>
        }
        if (this.state.redirect) {
            return <Redirect push to="/application-create"/>;
        }
        const {classes} = this.props;
        const api = this.state.api;

        return (
            this.state.api ?

                    <Grid container className="tab-grid" spacing={0}>
                        {/*<Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <Edit /> Edit
                                 </Button>
                                 <Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <CreateNewFolder /> Create New Version
                                 </Button>
                                 <Button aria-owns="simple-menu" aria-haspopup="true" >
                                 <Description /> View Swagger
                                 </Button>*/}
                        <Grid item xs={12} sm={12} md={6} lg={3} xl={2}>
                            <Card>
                                <CardMedia className={classes.media}
                                           image="/store/public/app/images/api/api-default.png"
                                           title="API icon"
                                />
                                <CardContent>
                                    <Typography type="headline" component="h2">
                                        {api.name}
                                    </Typography>
                                    <Typography type="subheading" color="secondary">
                                        {api.version} by {api.provider}
                                    </Typography>
                                    <StarRatingBar apiIdProp={this.api_uuid}></StarRatingBar>
                                </CardContent>
                                <Divider/>
                                <CardActions disableActionSpacing>
                                    <IconButton aria-label="Add to favorites">
                                        <FavoriteIcon/>
                                    </IconButton>
                                    <IconButton aria-label="Share">
                                        <ShareIcon/>
                                    </IconButton>
                                    <IconButton aria-label="Embed">
                                        <CodeIcon/>
                                    </IconButton>
                                    <IconButton aria-label="Email">
                                        <EmailIcon/>
                                    </IconButton>
                                </CardActions>
                            </Card>
                            <Grid>
                                <Button onClick={this.openSubscribeMenu}> Subscribe to an
                                    Application </Button>
                                <Dialog open={this.state.openSubscribeMenu} transition={Slide}
                                        onClose={this.closeSubscribeMenu}>
                                    <DialogTitle>
                                        {"Subscribe"}
                                    </DialogTitle>
                                    <DialogContent>
                                        <DialogContentText>
                                            Select the Application name and Tier to Subscribe to an Application
                                        </DialogContentText>
                                        {this.state.options &&
                                        <FormControl style={{width: "100%", marginBottom: "20px"}}
                                                     className={classes.formControl}>
                                            <InputLabel>Applications</InputLabel>
                                            <Select
                                                style={{width: "100%"}}
                                                value={this.state.applicationId}
                                                onChange={this.handleChange('applicationId')}
                                            >
                                                {this.state.options.map((option) => <MenuItem key={option.value}
                                                                                value={option.value}>
                                                    {option.label}</MenuItem>)}
                                            </Select>
                                        </FormControl>
                                        }
                                        {this.state.tiers &&
                                        <FormControl style={{width: "100%"}}>
                                            <InputLabel>Tiers</InputLabel>
                                            <Select
                                                style={{width: "100%"}}
                                                value={this.state.policyName}
                                                onChange={this.handleChange('policyName')}
                                            >
                                                {this.state.tiers.map((tier) => <MenuItem key={tier.value}
                                                                                value={tier.value}>
                                                    {tier.label}</MenuItem>)}
                                            </Select>
                                        </FormControl>
                                        }

 </DialogContent>
                                    <DialogActions>
                                        <Button onClick={this.closeSubscribeMenu} color="primary">
                                            <NotificationSystem ref="notificationSystem"/>
                                            Cancel
                                        </Button>
                                        <Button onClick={this.createSubscription} color="primary">
                                            <NotificationSystem ref="notificationSystem"/>
                                            Subscribe
                                        </Button></DialogActions>

                                </Dialog>
                            </Grid>
                        </Grid>
                        <Grid item xs={12} sm={12} md={6} lg={4} xl={4} className="add-item-left-padding ">

                                <TableBody>
                                    <TableRow>
                                        <TableCell>
                                            Status</TableCell><TableCell><Badge status="processing"
                                                                                text={api.lifeCycleStatus}/></TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Context</TableCell><TableCell>{api.context}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Default API
                                            Version</TableCell><TableCell>{api.isDefaultVersion}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Date Created</TableCell><TableCell>{api.createdTime}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Date Last
                                            Updated</TableCell><TableCell>{api.lastUpdatedTime}</TableCell>
                                    </TableRow>
                                    <TableRow>
                                        <TableCell>Rate it</TableCell>
                                        <TableCell>
                                            <StarRatingBar apiIdProp={this.api_uuid}></StarRatingBar>
                                        </TableCell>
                                    </TableRow>
                                </TableBody>

                        </Grid>
                    </Grid>

                : <Loading/>
        );
    }
}

class Star extends React.Component {
    constructor(props) {
        super(props);

        this.handleHoveringOver = this.handleHoveringOver.bind(this);
    }

    handleHoveringOver(event) {
        this.props.hoverOver(this.props.name);
    }

    render() {
        return this.props.isRated ?

                ★
             :

                ☆
            ;
    }
}

class StarRatingBar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            previousRating: 0,
            rating: 0
        };

        this.handleMouseOver = this.handleMouseOver.bind(this);
        this.handleRatingUpdate = this.handleRatingUpdate.bind(this);
        this.handleMouseOut = this.handleMouseOut.bind(this);
    }

    componentDidMount() {
        var api = new Api();
        let promised_api = api.getAPIById(this.props.apiIdProp);
        promised_api.then(
            response => {
            }
        );

        //get user rating
        let promised_rating = api.getRatingFromUser(this.props.apiIdProp, null);
        promised_rating.then(
            response => {
                this.setState({rating: response.obj.userRating});
                this.setState({previousRating: response.obj.userRating});
            }
        );
    }

    handleMouseOver(index) {
        this.setState({rating: index});
    }

    handleMouseOut() {
        this.setState({rating: this.state.previousRating});
    }

    handleRatingUpdate() {
        this.setState({previousRating: this.state.rating});
        this.setState({rating: this.state.rating});

        var api = new Api();
        let ratingInfo = {"rating": this.state.rating};
        let promise = api.addRating(this.props.apiIdProp, ratingInfo);
        promise.then(
            response => {
                message.success("Rating updated successfully");
            }).catch(
            error => {
                message.error("Error occurred while adding ratings!");
            }
        );
    }

    render() {
        return (

            <Star name={1} isRated={this.state.rating >= 1} hoverOver={this.handleMouseOver}> </Star>
            <Star name={2} isRated={this.state.rating >= 2} hoverOver={this.handleMouseOver}> </Star>
            <Star name={3} isRated={this.state.rating >= 3} hoverOver={this.handleMouseOver}> </Star>
            <Star name={4} isRated={this.state.rating >= 4} hoverOver={this.handleMouseOver}> </Star>
            <Star name={5} isRated={this.state.rating >= 5} hoverOver={this.handleMouseOver}> </Star>

);
    }
}

export default withStyles(styles)(BasicInfo);
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { Button } from 'react-bootstrap';
import EntityRow from './EntityRow';
import userProfileImg from '../../images/user-profile-icon.png';
import styles from './styles.module.css';

export default class UserRow extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      propertyIds: this.getPropertyIds()
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.entityId !== this.props.entityId) {
      this.setState({
        propertyIds: Object.keys(nextProps.row)
      });
    }
  }

  getPropertyIds() {
    const { firstName, lastName, dob, row } = this.props;
    const propertyIds = Object.keys(row).filter((id) => {
      if (dob && id === dob.id) return false;
      return (id !== firstName.id && id !== lastName.id);
    });
    return propertyIds;
  }

  selectUser = () => {
    if (this.props.userPage) return;
    this.props.selectUserFn(this.props.entityId, this.props.row, this.props.entitySetId, this.props.propertyTypes);
  }

  renderBackButton = () => {
    if (!this.props.userPage) return null;
    return (

        <Button onClick={this.props.backFn} bsStyle="primary" className={styles.backButton}>Back to results</Button>

    );
  }

  getFirstNameVal = () => {
    return this.props.formatValueFn(this.props.row[this.props.firstName.id]);
  }

  getLastNameVal = () => {
    return this.props.formatValueFn(this.props.row[this.props.lastName.id]);
  }

  renderDOB = () => {
    if (!this.props.dob) return null;
    const dobVal = this.props.row[this.props.dob.id] || '';
    return
Date of Birth: {this.props.formatValueFn(dobVal)}
;
  }

  getClassName = () => {
    return (this.props.userPage) ? styles.userProfile : styles.userListItem;
  }

  renderUserProfile = () => {
    return (

First Name: {this.getFirstNameVal()}

Last Name: {this.getLastNameVal()}

          {this.renderDOB()}

    );
  }

  getContainerClassName = () => {
    return (this.props.userPage) ? '' : styles.userListContainer;
  }

  renderRow = () => {
    if (!this.props.userPage) return null;
    const row = Object.assign({}, this.props.row);
    delete row[this.props.firstName.id];
    delete row[this.props.lastName.id];
    if (this.props.dob) delete row[this.props.dob.id];
    return (
      <EntityRow
          row={row}
          entityId={this.props.entityId}
          entitySetId={this.props.entitySetId}
          formatValueFn={this.props.formatValueFn}
          propertyTypes={this.props.propertyTypes}
          onClick={this.props.onClick} />
    );
  }

  render() {
    return (

        {this.renderBackButton()}
        {this.renderUserProfile()}
        {this.renderRow()}

    );
  }

  static propTypes = {
    row: PropTypes.object.isRequired,
    entitySetId: PropTypes.string.isRequired,
    propertyTypes: PropTypes.array.isRequired,
    firstName: PropTypes.object.isRequired,
    lastName: PropTypes.object.isRequired,
    dob: PropTypes.object,
    selectUserFn: PropTypes.func,
    backFn: PropTypes.func,
    userPage: PropTypes.bool,
    formatValueFn: PropTypes.func,
    entityId: PropTypes.string,
    onClick: PropTypes.func.isRequired
  }
}
<commit_msg>fix user profile bug<commit_after>import React, { PropTypes } from 'react';
import { Button } from 'react-bootstrap';
import EntityRow from './EntityRow';
import userProfileImg from '../../images/user-profile-icon.png';
import styles from './styles.module.css';

export default class UserRow extends React.Component {

  selectUser = () => {
    if (this.props.userPage) return;
    this.props.selectUserFn(this.props.entityId, this.props.row, this.props.entitySetId, this.props.propertyTypes);
  }

  renderBackButton = () => {
    if (!this.props.userPage) return null;
    return (

        <Button onClick={this.props.backFn} bsStyle="primary" className={styles.backButton}>Back to results</Button>

    );
  }

  getFirstNameVal = () => {
    return this.getFormattedVal(this.props.firstName);
  }

  getLastNameVal = () => {
    return this.getFormattedVal(this.props.lastName);
  }

  renderDOB = () => {
    if (!this.props.dob) return null;
    return (

        Date of Birth: {this.getFormattedVal(this.props.dob)}

);
  }

  getFormattedVal = (prop) => {
    const id = prop.id;
    const fqn = `${prop.type.namespace}.${prop.type.name}`;
    const value = this.props.row[id] || this.props.row[fqn] || '';
    return this.props.formatValueFn(value);
  }

  getRowWithoutUserProfile = () => {
    const row = Object.assign({}, this.props.row);
    delete row[this.props.firstName.id];
    delete row[`${this.props.firstName.type.namespace}.${this.props.firstName.type.name}`];
    delete row[this.props.lastName.id];
    delete row[`${this.props.lastName.type.namespace}.${this.props.lastName.type.name}`];
    if (this.props.dob) {
      delete row[this.props.dob.id];
      delete row[`${this.props.dob.type.namespace}.${this.props.dob.type.name}`];
    }
    return row;
  }

  getClassName = () => {
    return (this.props.userPage) ? styles.userProfile : styles.userListItem;
  }

  renderUserProfile = () => {
    return (

First Name: {this.getFirstNameVal()}

Last Name: {this.getLastNameVal()}

          {this.renderDOB()}

    );
  }

  getContainerClassName = () => {
    return (this.props.userPage) ? '' : styles.userListContainer;
  }

  renderRow = () => {
    if (!this.props.userPage) return null;
    return (
      <EntityRow
          row={this.getRowWithoutUserProfile()}
          entityId={this.props.entityId}
          entitySetId={this.props.entitySetId}
          formatValueFn={this.props.formatValueFn}
          propertyTypes={this.props.propertyTypes}
          onClick={this.props.onClick} />
    );
  }

  render() {
    return (

        {this.renderBackButton()}
        {this.renderUserProfile()}
        {this.renderRow()}

    );
  }

  static propTypes = {
    row: PropTypes.object.isRequired,
    entitySetId: PropTypes.string.isRequired,
    propertyTypes: PropTypes.array.isRequired,
    firstName: PropTypes.object.isRequired,
    lastName: PropTypes.object.isRequired,
    dob: PropTypes.object,
    selectUserFn: PropTypes.func,
    backFn: PropTypes.func,
    userPage: PropTypes.bool,
    formatValueFn: PropTypes.func,
    entityId: PropTypes.string,
    onClick: PropTypes.func.isRequired
  }
}
<|endoftext|>


<commit_before>'use strict';

var React = require('react');

var NumeralFormatter = require('./shortcuts/NumeralFormatter');
var DateFormatter = require('./shortcuts/DateFormatter');
var PhoneFormatter = require('./shortcuts/PhoneFormatter');
var CreditCardDetector = require('./shortcuts/CreditCardDetector');
var Util = require('./utils/Util');
var DefaultProperties = require('./common/DefaultProperties');

var Cleave = React.createClass({
    componentDidMount: function () {
        this.init();
    },

    componentWillReceiveProps: function (nextProps) {
        var owner = this,
            phoneRegionCode = nextProps.options.phoneRegionCode,
            newValue = nextProps.value;

        if (newValue) {
            newValue = newValue.toString();

            if (newValue !== owner.properties.initValue) {
                owner.properties.initValue = newValue;
                owner.onInput(newValue);
            }
        }

        // update phone region code
        if (phoneRegionCode && phoneRegionCode !== owner.properties.phoneRegionCode) {
            owner.properties.phoneRegionCode = phoneRegionCode;
            owner.initPhoneFormatter();
            owner.onInput(owner.properties.result);
        }
    },

    getInitialState: function () {
        var owner = this,
            { value, options, onKeyDown, onChange, ...other } = owner.props;

        owner.registeredEvents = {
            onChange:  onChange || Util.noop,
            onKeyDown: onKeyDown || Util.noop
        };

        options.initValue = value;

        owner.properties = DefaultProperties.assign({}, options);

        return {
            other: other,
            value: owner.properties.result
        };
    },

    init: function () {
        var owner = this,
            pps = owner.properties;

        // so no need for this lib at all
        if (!pps.numeral && !pps.phone && !pps.creditCard && !pps.date && (pps.blocksLength === 0 && !pps.prefix)) {
            return;
        }

        pps.maxLength = Util.getMaxLength(pps.blocks);

        owner.initPhoneFormatter();
        owner.initDateFormatter();
        owner.initNumeralFormatter();

        owner.onInput(pps.initValue);
    },

    initNumeralFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.numeral) {
            return;
        }

        pps.numeralFormatter = new NumeralFormatter(
            pps.numeralDecimalMark,
            pps.numeralDecimalScale,
            pps.numeralThousandsGroupStyle,
            pps.delimiter
        );
    },

    initDateFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.date) {
            return;
        }

        pps.dateFormatter = new DateFormatter(pps.datePattern);
        pps.blocks = pps.dateFormatter.getBlocks();
        pps.blocksLength = pps.blocks.length;
        pps.maxLength = Util.getMaxLength(pps.blocks);
    },

    initPhoneFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.phone) {
            return;
        }

        // Cleave.AsYouTypeFormatter should be provided by
        // external google closure lib
        try {
            pps.phoneFormatter = new PhoneFormatter(
                new pps.root.Cleave.AsYouTypeFormatter(pps.phoneRegionCode),
                pps.delimiter
            );
        } catch (ex) {
            throw new Error('Please include phone-type-formatter.{country}.js lib');
        }
    },

    onKeyDown: function (event) {
        var owner = this,
            pps = owner.properties,
            charCode = event.which || event.keyCode;

        // hit backspace when last character is delimiter
        if (charCode === 8 && Util.isDelimiter(pps.result.slice(-1), pps.delimiter, pps.delimiters)) {
            pps.backspace = true;
        } else {
            pps.backspace = false;
        }

        owner.registeredEvents.onKeyDown(event);
    },

    onChange: function (event) {
        var owner = this, pps = owner.properties,
            rawValue;

        owner.onInput(event.target.value);

        rawValue = pps.result;

        if (pps.rawValueTrimPrefix) {
            rawValue = Util.getPrefixStrippedValue(rawValue, pps.prefix, pps.prefixLength);
        }

        if (pps.numeral) {
            rawValue = pps.numeralFormatter.getRawValue(rawValue);
        } else {
            rawValue = Util.stripDelimiters(rawValue, pps.delimiter, pps.delimiters);
        }

        event.target.rawValue = rawValue;
        event.target.value = pps.result;

        owner.registeredEvents.onChange(event);
    },

    onInput: function (value) {
        var owner = this, pps = owner.properties,
            prev = pps.result;

        // case 1: delete one more character "4"
        // 1234*| -> hit backspace -> 123|
        // case 2: last character is not delimiter which is:
        // 12|34* -> hit backspace -> 1|34*

        if (!pps.numeral && pps.backspace && !Util.isDelimiter(value.slice(-1), pps.delimiter, pps.delimiters)) {
            value = Util.headStr(value, value.length - 1);
        }

        // phone formatter
        if (pps.phone) {
            pps.result = pps.phoneFormatter.format(value);
            owner.updateValueState();

            return;
        }

        // numeral formatter
        if (pps.numeral) {
            pps.result = pps.prefix + pps.numeralFormatter.format(value);
            owner.updateValueState();

            return;
        }

        // date
        if (pps.date) {
            value = pps.dateFormatter.getValidatedDate(value);
        }

        // strip delimiters
        value = Util.stripDelimiters(value, pps.delimiter, pps.delimiters);

        // strip prefix
        value = Util.getPrefixStrippedValue(value, pps.prefix, pps.prefixLength);

        // strip non-numeric characters
        value = pps.numericOnly ? Util.strip(value, /[^\d]/g) : value;

        // convert case
        value = pps.uppercase ? value.toUpperCase() : value;
        value = pps.lowercase ? value.toLowerCase() : value;

        // prefix
        if (pps.prefix) {
            value = pps.prefix + value;

            // no blocks specified, no need to do formatting
            if (pps.blocksLength === 0) {
                pps.result = value;
                owner.updateValueState();

                return;
            }
        }

        // update credit card props
        if (pps.creditCard) {
            owner.updateCreditCardPropsByValue(value);
        }

        // strip over length characters
        value = Util.headStr(value, pps.maxLength);

        // apply blocks
        pps.result = Util.getFormattedValue(value, pps.blocks, pps.blocksLength, pps.delimiter, pps.delimiters);

        // nothing changed
        // prevent update value to avoid caret position change
        if (prev === pps.result && prev !== pps.prefix) {
            return;
        }

        owner.updateValueState();
    },

    updateCreditCardPropsByValue: function (value) {
        var owner = this, pps = owner.properties,
            creditCardInfo;

        // At least one of the first 4 characters has changed
        if (Util.headStr(pps.result, 4) === Util.headStr(value, 4)) {
            return;
        }

        creditCardInfo = CreditCardDetector.getInfo(value, pps.creditCardStrictMode);

        pps.blocks = creditCardInfo.blocks;
        pps.blocksLength = pps.blocks.length;
        pps.maxLength = Util.getMaxLength(pps.blocks);

        // credit card type changed
        if (pps.creditCardType !== creditCardInfo.type) {
            pps.creditCardType = creditCardInfo.type;

            pps.onCreditCardTypeChanged.call(owner, pps.creditCardType);
        }
    },

    updateValueState: function () {
        this.setState({value: this.properties.result});
    },

    render: function () {
        var owner = this;

        return (
            <input type="text" {...owner.state.other}
                   value={owner.state.value}
                   onKeyDown={owner.onKeyDown}
                   onChange={owner.onChange}/>
        );
    }
});

module.exports = Cleave;
<commit_msg>[Issue-92] Fix empty value prop not working issue<commit_after>'use strict';

var React = require('react');

var NumeralFormatter = require('./shortcuts/NumeralFormatter');
var DateFormatter = require('./shortcuts/DateFormatter');
var PhoneFormatter = require('./shortcuts/PhoneFormatter');
var CreditCardDetector = require('./shortcuts/CreditCardDetector');
var Util = require('./utils/Util');
var DefaultProperties = require('./common/DefaultProperties');

var Cleave = React.createClass({
    componentDidMount: function () {
        this.init();
    },

    componentWillReceiveProps: function (nextProps) {
        var owner = this,
            phoneRegionCode = nextProps.options.phoneRegionCode,
            newValue = nextProps.value;

        if (newValue !== undefined) {
            newValue = newValue.toString();

            if (newValue !== owner.properties.initValue) {
                owner.properties.initValue = newValue;
                owner.onInput(newValue);
            }
        }

        // update phone region code
        if (phoneRegionCode && phoneRegionCode !== owner.properties.phoneRegionCode) {
            owner.properties.phoneRegionCode = phoneRegionCode;
            owner.initPhoneFormatter();
            owner.onInput(owner.properties.result);
        }
    },

    getInitialState: function () {
        var owner = this,
            { value, options, onKeyDown, onChange, ...other } = owner.props;

        owner.registeredEvents = {
            onChange:  onChange || Util.noop,
            onKeyDown: onKeyDown || Util.noop
        };

        options.initValue = value;

        owner.properties = DefaultProperties.assign({}, options);

        return {
            other: other,
            value: owner.properties.result
        };
    },

    init: function () {
        var owner = this,
            pps = owner.properties;

        // so no need for this lib at all
        if (!pps.numeral && !pps.phone && !pps.creditCard && !pps.date && (pps.blocksLength === 0 && !pps.prefix)) {
            return;
        }

        pps.maxLength = Util.getMaxLength(pps.blocks);

        owner.initPhoneFormatter();
        owner.initDateFormatter();
        owner.initNumeralFormatter();

        owner.onInput(pps.initValue);
    },

    initNumeralFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.numeral) {
            return;
        }

        pps.numeralFormatter = new NumeralFormatter(
            pps.numeralDecimalMark,
            pps.numeralDecimalScale,
            pps.numeralThousandsGroupStyle,
            pps.delimiter
        );
    },

    initDateFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.date) {
            return;
        }

        pps.dateFormatter = new DateFormatter(pps.datePattern);
        pps.blocks = pps.dateFormatter.getBlocks();
        pps.blocksLength = pps.blocks.length;
        pps.maxLength = Util.getMaxLength(pps.blocks);
    },

    initPhoneFormatter: function () {
        var owner = this,
            pps = owner.properties;

        if (!pps.phone) {
            return;
        }

        // Cleave.AsYouTypeFormatter should be provided by
        // external google closure lib
        try {
            pps.phoneFormatter = new PhoneFormatter(
                new pps.root.Cleave.AsYouTypeFormatter(pps.phoneRegionCode),
                pps.delimiter
            );
        } catch (ex) {
            throw new Error('Please include phone-type-formatter.{country}.js lib');
        }
    },

    onKeyDown: function (event) {
        var owner = this,
            pps = owner.properties,
            charCode = event.which || event.keyCode;

        // hit backspace when last character is delimiter
        if (charCode === 8 && Util.isDelimiter(pps.result.slice(-1), pps.delimiter, pps.delimiters)) {
            pps.backspace = true;
        } else {
            pps.backspace = false;
        }

        owner.registeredEvents.onKeyDown(event);
    },

    onChange: function (event) {
        var owner = this, pps = owner.properties,
            rawValue;

        owner.onInput(event.target.value);

        rawValue = pps.result;

        if (pps.rawValueTrimPrefix) {
            rawValue = Util.getPrefixStrippedValue(rawValue, pps.prefix, pps.prefixLength);
        }

        if (pps.numeral) {
            rawValue = pps.numeralFormatter.getRawValue(rawValue);
        } else {
            rawValue = Util.stripDelimiters(rawValue, pps.delimiter, pps.delimiters);
        }

        event.target.rawValue = rawValue;
        event.target.value = pps.result;

        owner.registeredEvents.onChange(event);
    },

    onInput: function (value) {
        var owner = this, pps = owner.properties,
            prev = pps.result;

        // case 1: delete one more character "4"
        // 1234*| -> hit backspace -> 123|
        // case 2: last character is not delimiter which is:
        // 12|34* -> hit backspace -> 1|34*

        if (!pps.numeral && pps.backspace && !Util.isDelimiter(value.slice(-1), pps.delimiter, pps.delimiters)) {
            value = Util.headStr(value, value.length - 1);
        }

        // phone formatter
        if (pps.phone) {
            pps.result = pps.phoneFormatter.format(value);
            owner.updateValueState();

            return;
        }

        // numeral formatter
        if (pps.numeral) {
            pps.result = pps.prefix + pps.numeralFormatter.format(value);
            owner.updateValueState();

            return;
        }

        // date
        if (pps.date) {
            value = pps.dateFormatter.getValidatedDate(value);
        }

        // strip delimiters
        value = Util.stripDelimiters(value, pps.delimiter, pps.delimiters);

        // strip prefix
        value = Util.getPrefixStrippedValue(value, pps.prefix, pps.prefixLength);

        // strip non-numeric characters
        value = pps.numericOnly ? Util.strip(value, /[^\d]/g) : value;

        // convert case
        value = pps.uppercase ? value.toUpperCase() : value;
        value = pps.lowercase ? value.toLowerCase() : value;

        // prefix
        if (pps.prefix) {
            value = pps.prefix + value;

            // no blocks specified, no need to do formatting
            if (pps.blocksLength === 0) {
                pps.result = value;
                owner.updateValueState();

                return;
            }
        }

        // update credit card props
        if (pps.creditCard) {
            owner.updateCreditCardPropsByValue(value);
        }

        // strip over length characters
        value = Util.headStr(value, pps.maxLength);

        // apply blocks
        pps.result = Util.getFormattedValue(value, pps.blocks, pps.blocksLength, pps.delimiter, pps.delimiters);

        // nothing changed
        // prevent update value to avoid caret position change
        if (prev === pps.result && prev !== pps.prefix) {
            return;
        }

        owner.updateValueState();
    },

    updateCreditCardPropsByValue: function (value) {
        var owner = this, pps = owner.properties,
            creditCardInfo;

        // At least one of the first 4 characters has changed
        if (Util.headStr(pps.result, 4) === Util.headStr(value, 4)) {
            return;
        }

        creditCardInfo = CreditCardDetector.getInfo(value, pps.creditCardStrictMode);

        pps.blocks = creditCardInfo.blocks;
        pps.blocksLength = pps.blocks.length;
        pps.maxLength = Util.getMaxLength(pps.blocks);

        // credit card type changed
        if (pps.creditCardType !== creditCardInfo.type) {
            pps.creditCardType = creditCardInfo.type;

            pps.onCreditCardTypeChanged.call(owner, pps.creditCardType);
        }
    },

    updateValueState: function () {
        this.setState({value: this.properties.result});
    },

    render: function () {
        var owner = this;

        return (
            <input type="text" {...owner.state.other}
                   value={owner.state.value}
                   onKeyDown={owner.onKeyDown}
                   onChange={owner.onChange}/>
        );
    }
});

module.exports = Cleave;
<|endoftext|>


<commit_before>import test from 'ava';
import React from 'react';
import {shallow, mount} from 'enzyme';
import ReactDOM from 'react-dom';

import ChartContainer from '../ChartContainer';
import { Chart } from '../../components/Chart'

test('renders chart', t => {
  /*const wrapper = shallow(
    <ChartContainer />
  )

  t.deepEqual(wrapper.find(Chart).length, 1);*/
  t.pass();
});
<commit_msg>fixed & extended ChartContainerTest<commit_after>import test from 'ava';
import React from 'react';
import {shallow, mount} from 'enzyme';
import ReactDOM from 'react-dom';
import configureStore from 'redux-mock-store'
import { Provider } from 'react-redux'

import ChartContainer from '../ChartContainer';
import { Chart } from '../../components/Chart'

const mockStore = configureStore();

const initialState = {
  progressData: [],
  progressLabels: [],
  maxpoints: 20
}

test('renders without crashing', t => {
  const store  = mockStore(initialState);
  const wrapper= shallow(
    <Provider store={store}>
      <ChartContainer />
    </Provider>
  );
  t.deepEqual(wrapper.find(ChartContainer).length, 1);
});

test('chartcontainer renders chart', t => {
  const store = mockStore(initialState);
  const wrapper = mount(
    <Provider store={store}>
      <ChartContainer />
    </Provider>
  );
  t.deepEqual(wrapper.find(Chart).length, 1);
});<|endoftext|>


<commit_before>/**
 * jQuery.spModal - A Modal Window System.
 *
 * This plugin requires:
 *      1. jQuery >= 2.1.3
 *      2. jQuery.ui >= 1.11.4
 *
 * @author    Gonzalo Chumillas <gchumillas@email.com>
 * @license   https://github.com/soloproyectos/jquery.modal/blob/master/LICENSE MIT License
 * @link      https://github.com/soloproyectos/jquery.modal
 */
(function ($) {
    var methods = {
        /**
         * Creates a modal window.
         *
         * A modal window is an iFrame covering all the available window. See the example included in
         * /demos/modal-window for more info.
         *
         * Example:
         * ```JavaScript
         * var mw = $.spModal('window', 'user-interface.html', {param1: 'one', param2: 'two'});
         * mw.on('event', function () {
         *      // Performs some actions and close the modal window
         *      mw.close();
         * });
         * ```
         *
         * @param {String} url    URL to the user interface
         * @param {Object} params Parameters (not required)
         *
         * @return {$.spModalWindow}
         */
        'window': function (url, params) {
            return new $.spModalWindow(url, params);
        },

        /**
         * User Interface class.
         *
         * See the example included in /demos/modal-window for more info.
         *
         * Example:
         * ```JavaScript
         * var target = $('#my-user-interface');
         * var ui = $.spModal('ui', target);
         *
         * // populates data
         * $('#title').text(ui.getParam('title'));
         * $('#message').text(ui.getParam('message'));
         *
         * $('#button1').on('click', function () {
         *      // tells the parent window to perform the action-1
         *      // the event will be captured by the parent window
         *      ui.trigger('action-1');
         * });
         * ```
         *
         * @param {jQuery.<HTMLElement>} target      User Interface
         * @param {jQuery.<HTMLElement>} modalWindow Modal window container (not required)
         *
         * @return {$.spModalUi}
         */
        'ui': function (target, modalWindow) {
            return new $.spModalUi(target, modalWindow);
        },

        /**
         * Modal message dialog.
         *
         * See the example included in /demos/modal-message for more info.
         *
         * Example:
         * ```JavaScript
         * var msg = $.spModal('message', 'My Title', 'This is a message...');
         * msg.setX(100);
         * msg.setY(50);
         * ```
         *
         * @param {String} title   Title
         * @param {String} message Message (not required)
         *
         * @return {$.spModalMessage}
         */
        'message': function (title, message) {
            return new $.spModalMessage(title, message);
        },

        /**
         * Modal loading dialog.
         *
         * See the example included in /demos/modal-loading for more info.
         *
         * Example:
         * ```JavaScript
         * var loading = $.spModal('loading', 'This process may take several minutes...');
         * loading.addButton('Cancel', function () {
         *      // canceling process...
         *      loading.close();
         * });
         * ```
         *
         * @param {String} message Message (not required)
         *
         * @return {$.spModalLoading}
         */
        'loading': function (message) {
            return new $.spModalLoading(message);
        },

        /**
         * Sends a GET request.
         *
         * This function uses internally the $.get function and accepts the same parameters. More info:
         * https://api.jquery.com/jquery.get/
         *
         * Example:
         * ```JavaScript
         * $.spModal('get', 'test.php', {one: 1, two: 2, three: 3}).always(function () {
         *     console.log('This is always executed');
         * }).done(function (data) {
         *     console.log('This is executed on success requests');
         * }).fail(function () {
         *     console.log('This is executed on failed requests');
         * });
         * ```
         *
         * @param {Mixed} args Additional arguments
         *
         * @return {jQuery.Promise}
         */
        'get': function (args) {
            // Based on a Matthew Crumley solution,
            // as we can't use the .apply() method in conjunction with the 'new' operator
            // http://goo.gl/PRL0eZ (redirects to http://stackoverflow.com)
            function F(args) {
                return $.spModalRequestGet.apply(this, args);
            }
            F.prototype = $.spModalRequestGet.prototype;

            var req = new F(arguments);
            return req.send();
        },

        /**
         * Sends a POST request.
         *
         * This function uses internally the $.get function and accepts the same parameters. More info:
         * https://api.jquery.com/jquery.post/
         *
         * Example:
         * ```JavaScript
         * $.spModal('post', 'test.php', {one: 1, two: 2, three: 3}).always(function () {
         *     console.log('This is always executed');
         * }).done(function (data) {
         *     console.log('This is executed on success requests');
         * }).fail(function () {
         *     console.log('This is executed on failed requests');
         * });
         * ```
         *
         * @param {Mixed} args Additional arguments
         *
         * @return {jQuery.Promise}
         */
        'post': function (args) {
            // Based on a Matthew Crumley solution,
            // as we can't use the .apply() method in conjunction with the 'new' operator
            // http://goo.gl/PRL0eZ (redirects to http://stackoverflow.com)
            function F(args) {
                return $.spModalRequestPost.apply(this, args);
            }
            F.prototype = $.spModalRequestPost.prototype;

            var req = new F(arguments);
            return req.send();
        },

        /**
         * Sends a POST request and uploads files.
         *
         * @param {jQuery.<HTMLInputElement>|String} input Input file(s)
         * @param {String}                           url   URL
         * @param {Object}                           data  Parameters (not required)
         *
         * @return {jQuery.Promise}
         */
        'upload': function (input, url, data) {
            var req = new $.spModalRequestUpload(input, url, data);
            return req.send();
        }
    };

    /**
     * Registers plugin.
     *
     * @param {String} methodName Method name
     * @param {Mixed}  args,...   Additional arguments (not required)
     *
     * @return {Mixed}
     */
    $.spModal = function (methodName, args) {
        var method = methods[methodName];
        var args = Array.prototype.slice.call(arguments, 1);

        if (method === undefined) {
            $.error('Method not found: ' + methodName);
        }

        return method.apply(this, args);
    };
})(jQuery);
<commit_msg>include example<commit_after>/**
 * jQuery.spModal - A Modal Window System.
 *
 * This plugin requires:
 *      1. jQuery >= 2.1.3
 *      2. jQuery.ui >= 1.11.4
 *
 * @author    Gonzalo Chumillas <gchumillas@email.com>
 * @license   https://github.com/soloproyectos/jquery.modal/blob/master/LICENSE MIT License
 * @link      https://github.com/soloproyectos/jquery.modal
 */
(function ($) {
    var methods = {
        /**
         * Creates a modal window.
         *
         * A modal window is an iFrame covering all the available window. See the example included in
         * /demos/modal-window for more info.
         *
         * Example:
         * ```JavaScript
         * var mw = $.spModal('window', 'user-interface.html', {param1: 'one', param2: 'two'});
         * mw.on('event', function () {
         *      // Performs some actions and close the modal window
         *      mw.close();
         * });
         * ```
         *
         * @param {String} url    URL to the user interface
         * @param {Object} params Parameters (not required)
         *
         * @return {$.spModalWindow}
         */
        'window': function (url, params) {
            return new $.spModalWindow(url, params);
        },

        /**
         * User Interface class.
         *
         * See the example included in /demos/modal-window for more info.
         *
         * Example:
         * ```JavaScript
         * var target = $('#my-user-interface');
         * var ui = $.spModal('ui', target);
         *
         * // populates data
         * $('#title').text(ui.getParam('title'));
         * $('#message').text(ui.getParam('message'));
         *
         * $('#button1').on('click', function () {
         *      // tells the parent window to perform the action-1
         *      // the event will be captured by the parent window
         *      ui.trigger('action-1');
         * });
         * ```
         *
         * @param {jQuery.<HTMLElement>} target      User Interface
         * @param {jQuery.<HTMLElement>} modalWindow Modal window container (not required)
         *
         * @return {$.spModalUi}
         */
        'ui': function (target, modalWindow) {
            return new $.spModalUi(target, modalWindow);
        },

        /**
         * Modal message dialog.
         *
         * See the example included in /demos/modal-message for more info.
         *
         * Example:
         * ```JavaScript
         * var msg = $.spModal('message', 'My Title', 'This is a message...');
         * msg.setX(100);
         * msg.setY(50);
         * ```
         *
         * @param {String} title   Title
         * @param {String} message Message (not required)
         *
         * @return {$.spModalMessage}
         */
        'message': function (title, message) {
            return new $.spModalMessage(title, message);
        },

        /**
         * Modal loading dialog.
         *
         * See the example included in /demos/modal-loading for more info.
         *
         * Example:
         * ```JavaScript
         * var loading = $.spModal('loading', 'This process may take several minutes...');
         * loading.addButton('Cancel', function () {
         *      // canceling process...
         *      loading.close();
         * });
         * ```
         *
         * @param {String} message Message (not required)
         *
         * @return {$.spModalLoading}
         */
        'loading': function (message) {
            return new $.spModalLoading(message);
        },

        /**
         * Sends a GET request.
         *
         * This function uses internally the $.get function and accepts the same parameters. More info:
         * https://api.jquery.com/jquery.get/
         *
         * Example:
         * ```JavaScript
         * $.spModal('get', 'test.php', {one: 1, two: 2, three: 3}).always(function () {
         *     console.log('This is always executed');
         * }).done(function (data) {
         *     console.log('This is executed on success requests');
         * }).fail(function () {
         *     console.log('This is executed on failed requests');
         * });
         * ```
         *
         * @param {Mixed} args Additional arguments
         *
         * @return {jQuery.Promise}
         */
        'get': function (args) {
            // Based on a Matthew Crumley solution,
            // as we can't use the .apply() method in conjunction with the 'new' operator
            // http://goo.gl/PRL0eZ (redirects to http://stackoverflow.com)
            function F(args) {
                return $.spModalRequestGet.apply(this, args);
            }
            F.prototype = $.spModalRequestGet.prototype;

            var req = new F(arguments);
            return req.send();
        },

        /**
         * Sends a POST request.
         *
         * This function uses internally the $.get function and accepts the same parameters. More info:
         * https://api.jquery.com/jquery.post/
         *
         * Example:
         * ```JavaScript
         * $.spModal('post', 'test.php', {one: 1, two: 2, three: 3}).always(function () {
         *     console.log('This is always executed');
         * }).done(function (data) {
         *     console.log('This is executed on success requests');
         * }).fail(function () {
         *     console.log('This is executed on failed requests');
         * });
         * ```
         *
         * @param {Mixed} args Additional arguments
         *
         * @return {jQuery.Promise}
         */
        'post': function (args) {
            // Based on a Matthew Crumley solution,
            // as we can't use the .apply() method in conjunction with the 'new' operator
            // http://goo.gl/PRL0eZ (redirects to http://stackoverflow.com)
            function F(args) {
                return $.spModalRequestPost.apply(this, args);
            }
            F.prototype = $.spModalRequestPost.prototype;

            var req = new F(arguments);
            return req.send();
        },

        /**
         * Sends a POST request and uploads files.
         *
         * Example:
         * ```JavaScript
         * var inputFile = $('#file');
         * inputFile.change(function () {
         *     $.spModal('upload', inputFile, 'test.php', {one: 1, two: 2}).done(function (data) {
         *         console.log(data);
         *     }).fail(function () {
         *         console.log('failed!');
         *     });
         * });
         * ```
         *
         * @param {jQuery.<HTMLInputElement>|String} input Input file(s)
         * @param {String}                           url   URL
         * @param {Object}                           data  Parameters (not required)
         *
         * @return {jQuery.Promise}
         */
        'upload': function (input, url, data) {
            var req = new $.spModalRequestUpload(input, url, data);
            return req.send();
        }
    };

    /**
     * Registers plugin.
     *
     * @param {String} methodName Method name
     * @param {Mixed}  args,...   Additional arguments (not required)
     *
     * @return {Mixed}
     */
    $.spModal = function (methodName, args) {
        var method = methods[methodName];
        var args = Array.prototype.slice.call(arguments, 1);

        if (method === undefined) {
            $.error('Method not found: ' + methodName);
        }

        return method.apply(this, args);
    };
})(jQuery);
<|endoftext|>


<commit_before>ngapp.controller('treeSearchController', function($scope, $q, $timeout, progressService, hotkeyService, hotkeyFactory, errorService) {
    // helper variables
    let aKey = 65, eKey = 69, fKey = 70, nKey = 78,
        searchOptionKeys = [fKey, eKey, nKey, aKey];

    // scope variables
    $scope.search = '';
    $scope.showExactMatch = true;
    $scope.searchOptions = { searchBy: 'Editor ID', exact: true };
    $scope.searchBy = ['Form ID', 'Editor ID', 'Name'];

    // inherited functions
    hotkeyService.buildOnKeyDown($scope, 'onSearchKeyDown', 'treeSearch');

    // helper functions
    let getElementIndex = function(elements, element) {
        return elements.findIndex(function(e) {
            return xelib.ElementEquals(e, element);
        });
    };

    let getStartIndex = function(files, file, reverse, noOffset) {
        if (file) {
            return getElementIndex(files, file) + noOffset ? 0 : (reverse ? -1 : 1);
        } else {
            return reverse ? files.length : 0;
        }
    };

    let findExactMatch = function(search, reverse = false) {
        let action = $q.defer();
        $timeout(function() {
            let start = Date.now(),
                result = 0,
                currentNode = $scope.lastSelectedNode(),
                currentFile = currentNode && xelib.GetElementFile(currentNode.handle),
                currentNodeIsFile = currentNode && currentNode.element_type === xelib.etFile;
            xelib.WithHandles(xelib.GetElements(0, ''), function(files) {
                let startIndex = getStartIndex(files, currentFile, reverse, currentNodeIsFile);
                for (let i = startIndex; i >= 0 && i < files.length; reverse ? i-- : i++) {
                    if ($scope.cancelled) return;
                    result = xelib.GetElement(files[i], search);
                    if (result) return;
                }
            });
            console.log(`Search completed in ${Date.now() - start}ms`);
            action.resolve(result);
        }, 100);
        return action.promise;
    };

    let findPartialMatch = function(search, byName, reverse) {
        let action = $q.defer();
        $timeout(function() {
            let functionName = `Find${(reverse ? 'Previous' : 'Next')}Record`,
                node = $scope.lastSelectedNode(),
                handle = node ? node.handle : 0,
                result = xelib[functionName](handle, search, !byName, byName);
            action.resolve(result);
        }, 100);
        return action.promise;
    };

    let findElement = function(reverse) {
        let byName = $scope.searchOptions.searchBy === 'Name',
            search = $scope.search;
        // search by FormID is always exact
        if ($scope.searchOptions.exact) {
            // search by FormID uses the same syntax as search by EditorID
            return findExactMatch(byName ? `"${search}"` : search, reverse);
        } else {
            return findPartialMatch(search, byName, reverse);
        }
    };

    // scope functions
    $scope.foundResult = function(handle) {
        if ($scope.handle) xelib.Release($scope.handle);
        $scope.handle = handle;
        errorService.try(() => $scope.navigateToElement(handle));
    };

    $scope.previousResult = function() {
        progressService.showProgress({ message: 'Searching...' });
        findElement(true).then(function(handle) {
            $scope.notFound = !handle;
            if (handle) $scope.foundResult(handle);
            progressService.hideProgress();
        });
    };

    $scope.nextResult = function() {
        progressService.showProgress({ message: 'Searching...' });
        findElement().then(function(handle) {
            $scope.notFound = !handle;
            if (handle) $scope.foundResult(handle);
            progressService.hideProgress();
        });
    };

    $scope.closeSearch = function() {
        if ($scope.handle) xelib.Release($scope.handle);
        $scope.toggleSearchBar();
    };

    $scope.blurSearch = function() {
        $scope.notFound = false;
    };

    $scope.toggleExact = function() {
        $scope.searchOptions.exact = !$scope.searchOptions.exact;
    };

    $scope.setSearchBy = function(e) {
        let n = searchOptionKeys.indexOf(e.keyCode);
        if (n === -1) return;
        $scope.searchOptions.searchBy = n.toString();
    };

    // event listeners
    $scope.$on('cancel', () => $scope.cancelled = true);
});
<commit_msg>refactored treeSearchController and fixed setSearchBy<commit_after>ngapp.controller('treeSearchController', function($scope, $q, $timeout, progressService, hotkeyService, hotkeyFactory, errorService) {
    // helper variables
    let eKey = 69, fKey = 70, nKey = 78,
        searchOptionKeys = [fKey, eKey, nKey];

    // scope variables
    $scope.search = '';
    $scope.showExactMatch = true;
    $scope.searchOptions = { searchBy: 'Editor ID', exact: true };
    $scope.searchBy = ['Form ID', 'Editor ID', 'Name'];

    // inherited functions
    hotkeyService.buildOnKeyDown($scope, 'onSearchKeyDown', 'treeSearch');

    // helper functions
    let getElementIndex = function(elements, element) {
        return elements.findIndex(function(e) {
            return xelib.ElementEquals(e, element);
        });
    };

    let getSearchFiles = function(files, file, reverse, noOffset) {
        let startIndex = 0;
        if (file) {
            startIndex = getElementIndex(files, file);
            startIndex += noOffset ? 0 : (reverse ? -1 : 1);
        }
        files = files.slice(startIndex);
        if (reverse) return files.reverse();
        return files;
    };

    let getExactMatch = function(file, nodeIsFile, search, reverse) {
        let result = 0;
        xelib.WithHandles(xelib.GetElements(0, ''), function(files) {
            let searchFiles = getSearchFiles(files, file, reverse, nodeIsFile);
            searchFiles.find(function(file) {
                if ($scope.cancelled) return true;
                result = xelib.GetElement(file, search);
                return result > 0;
            });
        });
    };

    let findExactMatch = function(search, reverse = false) {
        let action = $q.defer();
        $timeout(function() {
            let start = Date.now(),
                node = $scope.lastSelectedNode(),
                file = node && xelib.GetElementFile(node.handle),
                nodeIsFile = node && node.element_type === xelib.etFile,
                result = getExactMatch(file, nodeIsFile, search, reverse);
            console.log(`Search completed in ${Date.now() - start}ms`);
            action.resolve(result);
        }, 100);
        return action.promise;
    };

    let findPartialMatch = function(search, byName, reverse) {
        let action = $q.defer();
        $timeout(function() {
            let functionName = `Find${(reverse ? 'Previous' : 'Next')}Record`,
                node = $scope.lastSelectedNode(),
                handle = node ? node.handle : 0,
                result = xelib[functionName](handle, search, !byName, byName);
            action.resolve(result);
        }, 100);
        return action.promise;
    };

    let findElement = function(reverse) {
        let byName = $scope.searchOptions.searchBy === 'Name',
            search = $scope.search;
        // search by FormID is always exact
        if ($scope.searchOptions.exact) {
            // search by FormID uses the same syntax as search by EditorID
            return findExactMatch(byName ? `"${search}"` : search, reverse);
        } else {
            return findPartialMatch(search, byName, reverse);
        }
    };

    // scope functions
    $scope.foundResult = function(handle) {
        if ($scope.handle) xelib.Release($scope.handle);
        $scope.handle = handle;
        errorService.try(() => $scope.navigateToElement(handle));
    };

    $scope.previousResult = function() {
        progressService.showProgress({ message: 'Searching...' });
        findElement(true).then(function(handle) {
            $scope.notFound = !handle;
            if (handle) $scope.foundResult(handle);
            progressService.hideProgress();
        });
    };

    $scope.nextResult = function() {
        progressService.showProgress({ message: 'Searching...' });
        findElement().then(function(handle) {
            $scope.notFound = !handle;
            if (handle) $scope.foundResult(handle);
            progressService.hideProgress();
        });
    };

    $scope.closeSearch = function() {
        if ($scope.handle) xelib.Release($scope.handle);
        $scope.toggleSearchBar();
    };

    $scope.blurSearch = function() {
        $scope.notFound = false;
    };

    $scope.toggleExact = function() {
        $scope.searchOptions.exact = !$scope.searchOptions.exact;
    };

    $scope.setSearchBy = function(e) {
        let n = searchOptionKeys.indexOf(e.keyCode);
        if (n === -1) return;
        $scope.searchOptions.searchBy = $scope.searchBy[n];
    };

    // event listeners
    $scope.$on('cancel', () => $scope.cancelled = true);
});
<|endoftext|>