<commit_before>var React = require('react');
var axios = require('axios');

export default class ScenariosItem extends React.Component {
    constructor() {
        super();
        this.state = {
            type: 'scenario_object',
            angle: '',
            size: '1',
            posx: '',
            posy: '',
            items: [],
            numBots: 0,
            filename: "testscenario.txt",
            position: ''
        };

        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleRemove = this.handleRemove.bind(this);

        this.addScenario = this.addScenario.bind(this);
        this.saveScenario = this.saveScenario.bind(this);
        this.loadScenario = this.loadScenario.bind(this);
    }

    /* handler for add scenario (load currently displayed scenario into simulator) */
    addScenario(event){
        console.log("add scenario listener");
        axios({
            method:'POST',
            url:'/addScenario',
            data: JSON.stringify({items: this.state.items}),
            dataType: 'text',
            contentType: 'application/json; charset=utf-8'
        })
        .then(function(response) {
            console.log('added scenario successfully');
        })
        .catch(function (error) {
            console.log(error);
        });
    }

    /* saves currently loaded scenario to file */
    saveScenario(){
        console.log("save scenario listener");

        var scenario = {items: this.state.items};
        console.log("numBots:" + this.state.numBots);
        if (this.state.numBots != 1) alert("There must be exactly one bot!");
        else {
            //Implemented the same way as Python script saving. This might not work so use axios code if it doesn't
            //event . preventDefault ()
            var element = document.createElement('a');
            element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(this.state.items)));
            element.setAttribute('download', this.state.filename);
            element.style.display = 'none';
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);

            // axios({
            //     method:'POST',
            //     url:'/saveScenario',
            //     data: {scenario: scenario, name: filename},
            //     dataType: 'text',
            //     contentType: 'application/json; charset=utf-8'
            // })
            // .then(function(response) {
            //     console.log('saved scenario successfully');
            // })
            // .catch(function (error) {
            //     console.log(error);
            // });
        }

    }

    /* handler for load scenario (load scenario from file) */
    loadScenario(event){
        console.log("loading scenario listener");
        //implement the same way as python script upload button in interface
        var _this = this;
        var file = event.target.files[0];
        var reader = new FileReader();
        reader.onload = function(event) {
            var scenario = JSON.parse(event.target.result).items;
            _this.setState({items: scenario});
        };
        reader.readAsText(file);
        console.log("done");
    }

    /* handles input change for input fields */
    handleInputChange(event) {
        console.log("handle input change");
        console.log(this.state);
        const target = event.target;
        const value = target.value;
        const name = target.name;
        this.setState({
            [name]: value
        });
    }

    /* checks that object contains correct info and adds object to list*/
    handleSubmit() {
        console.log("handle submit");
        console.log(this.state);

        //check that inputs are valid
        if (this.state.angle > 360) alert("The angle is too large!");
        else if (this.state.angle == '' || this.state.posx == '' || this.state.posy == '') alert("Fields cannot be empty!");
        else {
            var li = this.state.items;
            var string = "[" + this.state.posx + "," + this.state.posy + "]";
            console.log(this.state.type);

            if (this.state.type == "simulator.simbot") {
                console.log("add bot");
                this.state.numBots++;
                console.log("numBot:" + this.state.numBots);
                li.push({type: this.state.type, angle: this.state.angle, position: string});
            } else {
                li.push({type: this.state.type, angle: this.state.angle, size: this.state.size, position: string});
            }

            this.setState({items: li});
        }
    }

    /* removes selected object from list*/
    handleRemove(event) {
        console.log("handle remove");
        console.log(this.state);
        var li = this.state.items;
        if (li[event.idx].type == "simulator.simbot") {
            this.state.numBots--;
        }
        console.log("type1: " + li[event.idx].type);
        console.log("numBot: " + this.state.numBots);
        li.splice(event.idx, 1);
        this.setState({items: li});
    }

    render() {
        var styles = {
            ScenariosItem: {
                padding: '10px',
                marginTop: '10px',
                marginRight: '10px'
            },

            Form: {
                marginLeft: '15px',
                marginRight: '15px',
                marginTop: '5px',
                marginBottom: '5px'
            },

            Button: {
                marginLeft: '10px',
                marginRight: '15px'
            }
        }
        var _this = this;
        return(

                <button onClick={this.saveScenario} style={styles.Button}>Save</button>
                <button style={styles.Button}>Load</button>
                <button style={styles.Button}>Add to Simulator</button>

                            Type:

                                <select name="type" value={this.state.value} onChange={this.handleInputChange} style={styles.Form}>
                                    <option value ="scenario_object">Scenario Object</option>
                                    <option value = "simulator.simbot">Simulated Minibot</option>
                                </select>

                            <button style={styles.Button} onClick={this.handleSubmit}>Add</button>

                            Angle:
                            <input type="number" name="angle" onChange={this.handleInputChange} style={styles.Form}/>
                            Size:
                            <input type="number" name="size"  disabled={this.state.type == "simulator.simbot"} onChange={this.handleInputChange} style={styles.Form}/>

                            Position X:
                            <input type="number" name="posx" onChange={this.handleInputChange} style={styles.Form}/>
                            Position Y:
                            <input type="number" name="posy" onChange={this.handleInputChange} style={styles.Form}/>

                {this.state.items.map(function (item, idx) {
                    return(

                                        Type:
                                        {item.type}

                                        Angle:
                                        {item.angle}
                                        Size:
                                        {item.size}

                                        Position:
                                        {item.position}
                                        <button style={styles.Button} onClick = {() => _this.handleRemove({idx})}>Remove</button>

                    );
                })
                }

        );
    }
}

// /**loading a scenario - just type in a name, no need for directory or file
//  extension*/
// $('#loadScenario').click(function() {
//     active_bots = [];
//     discovered_bots = [];
//
//     var filename = $("#scenarioname").val();
//     console.log("loading scenario: "+filename.toString());
//     $.ajax({
//         method: "POST",
//         url: '/loadScenario',
//         dataType: 'text',
//         data: JSON.stringify({'name':filename.toString()}),
//         contentType: 'application/json; charset=utf-8',
//         success: function (data){
//             $("#scenario").val(data);
//             console.log("successfully loaded scenario: "+data);
//         },
//         error: function(data){
//             console.log("error: please enter the name of an existing scenario")
//         }
//     });
// });<commit_msg>migrated check for numBot<commit_after>var React = require('react');
var axios = require('axios');

export default class ScenariosItem extends React.Component {
    constructor() {
        super();
        this.state = {
            type: 'scenario_object',
            angle: '',
            size: '1',
            posx: '',
            posy: '',
            items: [],
            numBots: 0,
            filename: "testscenario.txt",
            position: ''
        };

        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleRemove = this.handleRemove.bind(this);

        this.addScenario = this.addScenario.bind(this);
        this.saveScenario = this.saveScenario.bind(this);
        this.loadScenario = this.loadScenario.bind(this);
    }

    /* handler for add scenario (load currently displayed scenario into simulator) */
    addScenario(event){
        console.log("add scenario listener");
        axios({
            method:'POST',
            url:'/addScenario',
            data: JSON.stringify({items: this.state.items}),
            dataType: 'text',
            contentType: 'application/json; charset=utf-8'
        })
        .then(function(response) {
            console.log('added scenario successfully');
        })
        .catch(function (error) {
            console.log(error);
        });
    }

    /* saves currently loaded scenario to file */
    saveScenario(){
        console.log("save scenario listener");

        var scenario = {items: this.state.items};
        console.log("numBots:" + this.state.numBots);
        if (this.state.numBots != 1) alert("You need to add a bot!");
        else {
            //Implemented the same way as Python script saving. This might not work so use axios code if it doesn't
            //event . preventDefault ()
            var element = document.createElement('a');
            element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(this.state.items)));
            element.setAttribute('download', this.state.filename);
            element.style.display = 'none';
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);

            // axios({
            //     method:'POST',
            //     url:'/saveScenario',
            //     data: {scenario: scenario, name: filename},
            //     dataType: 'text',
            //     contentType: 'application/json; charset=utf-8'
            // })
            // .then(function(response) {
            //     console.log('saved scenario successfully');
            // })
            // .catch(function (error) {
            //     console.log(error);
            // });
        }

    }

    /* handler for load scenario (load scenario from file) */
    loadScenario(event){
        console.log("loading scenario listener");
        //implement the same way as python script upload button in interface
        var _this = this;
        var file = event.target.files[0];
        var reader = new FileReader();
        reader.onload = function(event) {
            var scenario = JSON.parse(event.target.result).items;
            _this.setState({items: scenario});
        };
        reader.readAsText(file);
        console.log("done");
    }

    /* handles input change for input fields */
    handleInputChange(event) {
        console.log("handle input change");
        console.log(this.state);
        const target = event.target;
        const value = target.value;
        const name = target.name;
        this.setState({
            [name]: value
        });
    }

    /* checks that object contains correct info and adds object to list*/
    handleSubmit() {
        console.log("handle submit");
        console.log(this.state);

        //check that inputs are valid
        if (this.state.angle > 360) alert("The angle is too large!");
        else if (this.state.type == 'simulator.simbot' && this.state.numBots == 1) alert("You already have one bot!");
        else if (this.state.angle == '' || this.state.posx == '' || this.state.posy == '') alert("Fields cannot be empty!");
        else {
            var li = this.state.items;
            var string = "[" + this.state.posx + "," + this.state.posy + "]";
            console.log(this.state.type);

            if (this.state.type == "simulator.simbot") {
                console.log("add bot");
                this.state.numBots++;
                console.log("numBot:" + this.state.numBots);
                li.push({type: this.state.type, angle: this.state.angle, position: string});
            } else {
                li.push({type: this.state.type, angle: this.state.angle, size: this.state.size, position: string});
            }

            this.setState({items: li});
        }
    }

    /* removes selected object from list*/
    handleRemove(event) {
        console.log("handle remove");
        console.log(this.state);
        var li = this.state.items;
        if (li[event.idx].type == "simulator.simbot") {
            this.state.numBots--;
        }
        console.log("type1: " + li[event.idx].type);
        console.log("numBot: " + this.state.numBots);
        li.splice(event.idx, 1);
        this.setState({items: li});
    }

    render() {
        var styles = {
            ScenariosItem: {
                padding: '10px',
                marginTop: '10px',
                marginRight: '10px'
            },

            Form: {
                marginLeft: '15px',
                marginRight: '15px',
                marginTop: '5px',
                marginBottom: '5px'
            },

            Button: {
                marginLeft: '10px',
                marginRight: '15px'
            }
        }
        var _this = this;
        return(

                <button onClick={this.saveScenario} style={styles.Button}>Save</button>
                <button style={styles.Button}>Load</button>
                <button style={styles.Button}>Add to Simulator</button>

                            Type:

                                <select name="type" value={this.state.value} onChange={this.handleInputChange} style={styles.Form}>
                                    <option value ="scenario_object">Scenario Object</option>
                                    <option value = "simulator.simbot">Simulated Minibot</option>
                                </select>

                            <button style={styles.Button} onClick={this.handleSubmit}>Add</button>

                            Angle:
                            <input type="number" name="angle" onChange={this.handleInputChange} style={styles.Form}/>
                            Size:
                            <input type="number" name="size"  disabled={this.state.type == "simulator.simbot"} onChange={this.handleInputChange} style={styles.Form}/>

                            Position X:
                            <input type="number" name="posx" onChange={this.handleInputChange} style={styles.Form}/>
                            Position Y:
                            <input type="number" name="posy" onChange={this.handleInputChange} style={styles.Form}/>

                {this.state.items.map(function (item, idx) {
                    return(

                                        Type:
                                        {item.type}

                                        Angle:
                                        {item.angle}
                                        Size:
                                        {item.size}

                                        Position:
                                        {item.position}
                                        <button style={styles.Button} onClick = {() => _this.handleRemove({idx})}>Remove</button>

                    );
                })
                }

        );
    }
}

// /**loading a scenario - just type in a name, no need for directory or file
//  extension*/
// $('#loadScenario').click(function() {
//     active_bots = [];
//     discovered_bots = [];
//
//     var filename = $("#scenarioname").val();
//     console.log("loading scenario: "+filename.toString());
//     $.ajax({
//         method: "POST",
//         url: '/loadScenario',
//         dataType: 'text',
//         data: JSON.stringify({'name':filename.toString()}),
//         contentType: 'application/json; charset=utf-8',
//         success: function (data){
//             $("#scenario").val(data);
//             console.log("successfully loaded scenario: "+data);
//         },
//         error: function(data){
//             console.log("error: please enter the name of an existing scenario")
//         }
//     });
// });<|endoftext|>


<commit_before>'use strict';

// Force NODE_ENV (and thus 'env' in express)
const ENV = process.env;

ENV.NODE_ENV = 'test';
ENV.ENABLE_CRAWLING = true;
// We use BCDN_HEADERS to distinguish between production and debug CDN headers
ENV.BCDN_HEADERS = ENV.BCDN_HEADERS || 'production';

const assert = require('assert').strict;
const { htmlEncode } = require('htmlencode');
const mockDate = require('mockdate');
const request = require('request');
const validator = require('html-validator');

const app = require('../app.js');
const config = require('../config');

// The server object holds the server instance across all tests;
// We start it in the first test and close it in the last one,
// otherwise test time increases a lot (more than 3x)
let server = {};

mockDate.set('03/05/2018');

function getExtension(str) {
    // use two enclosing parts; one for the dot (.)
    // and one for the extension itself.
    // So, the result we want is the third Array element,
    // since the first one is the whole match, the second one
    // returns the first captured match, etc.
    const match = str.match(/(\.)([a-zA-Z0-9]+)$/);

    return match && match[2];
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

// Just returning the existent config so that
// we don't have to import lib/helpers in tests.
function getConfig() {
    return config;
}

function cleanEndpoint(endpoint = '/') {
    // Maybe we should use node's `url` in this function
    if (!endpoint.startsWith('/')) {
        endpoint = `/${endpoint}`;
    }

    if (!endpoint.endsWith('/') && !endpoint.includes('?') && !getExtension(endpoint)) {
        endpoint = `${endpoint}/`;
    }

    return endpoint;
}

function getPort() {
    // don't use configured port
    const port = config.port < 3000 ? config.port + 3000 : config.port + 1;

    return port;
}

function getURI(endpoint) {
    const endp = cleanEndpoint(endpoint);
    const port = getPort();

    return `http://localhost:${port}${endp}`;
}

function startServer() {
    const port = getPort();

    if (server.listening) {
        return server;
    }

    server = app.listen(port);

    return server;
}

function stopServer(done) {
    return server.listening && server.close(done);
}

function prefetch(uri, cb) {
    const reqOpts = {
        uri,
        forever: true, // for 'connection: Keep-Alive'
        followRedirect: false,
        gzip: true
    };

    if (ENV.BCDN_HEADERS === 'debug') {
        reqOpts.headers = {
            Pragma: 'debug'
        };
    }

    request.get(reqOpts, (err, res) => {
        if (err) {
            return cb(err);
        }

        return cb(res);
    });
}

function assertValidHTML(res, cb) {
    const options = {
        data: res.body,
        format: 'text'
    };

    validator(options, (err, data) => {
        if (err) {
            return cb(err);
        }

        // Return when successful.
        if (data.includes('The document validates')) {
            return cb();
        }

        // Formatting output for readability.
        const errStr = `HTML Validation for '${res.request.path}' failed with:\n\t${data.replace('Error: ', '').split('\n').join('\n\t')}\n`;

        return cb(new Error(errStr));
    });
}

function assertItWorks(statusCode, cb) {
    try {
        assert.strictEqual(statusCode, 200);
        return cb();
    } catch (err) {
        return cb(err);
    }
}

function assertPageHeader(txt, res, cb) {
    const escapedTxt = escapeRegExp(txt);
    const re = new RegExp(`<h[1-6]( class=".+")?>(${escapedTxt})(</h[1-6]>)`);

    assert.ok(re.test(res.body), `Expects page header to be "${txt}"`);
    cb();
}

function assertPageBodyClass(bodyClass, res, cb) {
    const expected = `<body class="${bodyClass}`;

    assert.ok(res.body.includes(expected), `Expects page body class to include "${bodyClass}"`);
    cb();
}

function assertAuthors(res, cb) {
    const authors = config.authors.map((author) => author.name).join(', ');
    const authorsStr = `<meta name="author" content="${authors}">`;

    assert.ok(res.body.includes(authorsStr), `Expects response body to include "${authorsStr}"`);
    cb();
}

function cssHTML(uri, sri) {
    return htmlEncode(`<link href="${uri}" rel="stylesheet" integrity="${sri}" crossorigin="anonymous">`);
}

function cssJade(uri, sri) {
    return htmlEncode(`link(href="${uri}", rel="stylesheet", integrity="${sri}", crossorigin="anonymous")`);
}

function cssHAML(uri, sri) {
    return htmlEncode(`%link{href: "${uri}", rel: "stylesheet", integrity: "${sri}", crossorigin: "anonymous"}`);
}

function jsHTML(uri, sri) {
    return htmlEncode(`<script src="${uri}" integrity="${sri}" crossorigin="anonymous"></script>`);
}

function jsJade(uri, sri) {
    return htmlEncode(`script(src="${uri}", integrity="${sri}", crossorigin="anonymous")`);
}

function jsHAML(uri, sri) {
    return htmlEncode(`%script{src: "${uri}", integrity: "${sri}", crossorigin: "anonymous"}`);
}

module.exports = {
    getConfig,
    getExtension,
    getURI,
    startServer,
    stopServer,
    assert: {
        authors: assertAuthors,
        bodyClass: assertPageBodyClass,
        itWorks: assertItWorks,
        pageHeader: assertPageHeader,
        validHTML: assertValidHTML
    },
    prefetch,
    css: {
        pug: cssJade,
        html: cssHTML,
        haml: cssHAML
    },
    javascript: {
        pug: jsJade,
        html: jsHTML,
        haml: jsHAML
    }
};
<commit_msg>Specify `strictSSL: true` for request<commit_after>'use strict';

// Force NODE_ENV (and thus 'env' in express)
const ENV = process.env;

ENV.NODE_ENV = 'test';
ENV.ENABLE_CRAWLING = true;
// We use BCDN_HEADERS to distinguish between production and debug CDN headers
ENV.BCDN_HEADERS = ENV.BCDN_HEADERS || 'production';

const assert = require('assert').strict;
const { htmlEncode } = require('htmlencode');
const mockDate = require('mockdate');
const request = require('request');
const validator = require('html-validator');

const app = require('../app.js');
const config = require('../config');

// The server object holds the server instance across all tests;
// We start it in the first test and close it in the last one,
// otherwise test time increases a lot (more than 3x)
let server = {};

mockDate.set('03/05/2018');

function getExtension(str) {
    // use two enclosing parts; one for the dot (.)
    // and one for the extension itself.
    // So, the result we want is the third Array element,
    // since the first one is the whole match, the second one
    // returns the first captured match, etc.
    const match = str.match(/(\.)([a-zA-Z0-9]+)$/);

    return match && match[2];
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

// Just returning the existent config so that
// we don't have to import lib/helpers in tests.
function getConfig() {
    return config;
}

function cleanEndpoint(endpoint = '/') {
    // Maybe we should use node's `url` in this function
    if (!endpoint.startsWith('/')) {
        endpoint = `/${endpoint}`;
    }

    if (!endpoint.endsWith('/') && !endpoint.includes('?') && !getExtension(endpoint)) {
        endpoint = `${endpoint}/`;
    }

    return endpoint;
}

function getPort() {
    // don't use configured port
    const port = config.port < 3000 ? config.port + 3000 : config.port + 1;

    return port;
}

function getURI(endpoint) {
    const endp = cleanEndpoint(endpoint);
    const port = getPort();

    return `http://localhost:${port}${endp}`;
}

function startServer() {
    const port = getPort();

    if (server.listening) {
        return server;
    }

    server = app.listen(port);

    return server;
}

function stopServer(done) {
    return server.listening && server.close(done);
}

function prefetch(uri, cb) {
    const reqOpts = {
        uri,
        forever: true, // for 'connection: Keep-Alive'
        followRedirect: false,
        gzip: true,
        strictSSL: true
    };

    if (ENV.BCDN_HEADERS === 'debug') {
        reqOpts.headers = {
            Pragma: 'debug'
        };
    }

    request.get(reqOpts, (err, res) => {
        if (err) {
            return cb(err);
        }

        return cb(res);
    });
}

function assertValidHTML(res, cb) {
    const options = {
        data: res.body,
        format: 'text'
    };

    validator(options, (err, data) => {
        if (err) {
            return cb(err);
        }

        // Return when successful.
        if (data.includes('The document validates')) {
            return cb();
        }

        // Formatting output for readability.
        const errStr = `HTML Validation for '${res.request.path}' failed with:\n\t${data.replace('Error: ', '').split('\n').join('\n\t')}\n`;

        return cb(new Error(errStr));
    });
}

function assertItWorks(statusCode, cb) {
    try {
        assert.strictEqual(statusCode, 200);
        return cb();
    } catch (err) {
        return cb(err);
    }
}

function assertPageHeader(txt, res, cb) {
    const escapedTxt = escapeRegExp(txt);
    const re = new RegExp(`<h[1-6]( class=".+")?>(${escapedTxt})(</h[1-6]>)`);

    assert.ok(re.test(res.body), `Expects page header to be "${txt}"`);
    cb();
}

function assertPageBodyClass(bodyClass, res, cb) {
    const expected = `<body class="${bodyClass}`;

    assert.ok(res.body.includes(expected), `Expects page body class to include "${bodyClass}"`);
    cb();
}

function assertAuthors(res, cb) {
    const authors = config.authors.map((author) => author.name).join(', ');
    const authorsStr = `<meta name="author" content="${authors}">`;

    assert.ok(res.body.includes(authorsStr), `Expects response body to include "${authorsStr}"`);
    cb();
}

function cssHTML(uri, sri) {
    return htmlEncode(`<link href="${uri}" rel="stylesheet" integrity="${sri}" crossorigin="anonymous">`);
}

function cssJade(uri, sri) {
    return htmlEncode(`link(href="${uri}", rel="stylesheet", integrity="${sri}", crossorigin="anonymous")`);
}

function cssHAML(uri, sri) {
    return htmlEncode(`%link{href: "${uri}", rel: "stylesheet", integrity: "${sri}", crossorigin: "anonymous"}`);
}

function jsHTML(uri, sri) {
    return htmlEncode(`<script src="${uri}" integrity="${sri}" crossorigin="anonymous"></script>`);
}

function jsJade(uri, sri) {
    return htmlEncode(`script(src="${uri}", integrity="${sri}", crossorigin="anonymous")`);
}

function jsHAML(uri, sri) {
    return htmlEncode(`%script{src: "${uri}", integrity: "${sri}", crossorigin: "anonymous"}`);
}

module.exports = {
    getConfig,
    getExtension,
    getURI,
    startServer,
    stopServer,
    assert: {
        authors: assertAuthors,
        bodyClass: assertPageBodyClass,
        itWorks: assertItWorks,
        pageHeader: assertPageHeader,
        validHTML: assertValidHTML
    },
    prefetch,
    css: {
        pug: cssJade,
        html: cssHTML,
        haml: cssHAML
    },
    javascript: {
        pug: jsJade,
        html: jsHTML,
        haml: jsHAML
    }
};
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router-dom'
import Checkbox from 'material-ui/Checkbox';
import { ListItem } from 'material-ui/List';
import Divider from 'material-ui/Divider';
import FontIcon from 'material-ui/FontIcon';
import messages from 'lib/text'
import * as helper from 'lib/helper'
import style from './style.css'
import moment from 'moment';

const getOrderStateIcons = (order) => {
  let icons = [];

  if(order.hold) {
    icons.push(<FontIcon key="hold" title={messages.orders_hold} style={{ color: 'rgba(0, 0, 0, 0.2)'}} className="material-icons">pause_circle_outline</FontIcon>);
  }

  if(order.paid) {
    icons.push(<FontIcon key="paid" title={messages.orders_paid} style={{ color: 'rgba(251, 184, 41, 1)'}} className="material-icons">monetization_on</FontIcon>);
  }

  if(order.delivered) {
    icons.push(<FontIcon key="delivered" title={messages.orders_delivered} style={{ color: 'rgba(127, 175, 27, 1)'}} className="material-icons">local_shipping</FontIcon>);
  }

  if(order.cancelled) {
    return [<FontIcon key="cancelled" title={messages.orders_cancelled} style={{ color: 'rgba(0, 0, 0, 0.3)'}} className="material-icons">not_interested</FontIcon>];
  }

  if(order.closed) {
    return [<FontIcon key="closed" title={messages.orders_closed} style={{ color: 'rgba(127, 175, 27, 1)'}} className="material-icons">done</FontIcon>];
  }

  if(icons.length === 0 && order.draft){
    icons.unshift(<FontIcon key="draft" title={messages.orders_draft} style={{ color: 'rgba(0, 0, 0, 0.1)'}} className="material-icons">edit</FontIcon>);
  }

  return icons;
}

const OrdersListItem = ({ order, onSelect, selected, settings }) => {
  const checked = selected.includes(order.id);
  let grandTotalFormatted = helper.formatCurrency(order.grand_total, settings);

  const stateIcons = getOrderStateIcons(order);
  const dateCreated = moment(order.date_placed || order.date_created);
  const dateCreatedFromNow = dateCreated.fromNow();
  let shippingTo = order.shipping_address ? order.shipping_address.full_name : '';

  return (

      <ListItem style={{ cursor: 'normal' }}
        primaryText={

              <Checkbox checked={checked} onCheck={(event, isInputChecked) => { onSelect(order.id, isInputChecked); }} />

              {stateIcons}

              <Link to={`/admin/order/${order.id}`} className={style.number}>{order.number || 0}</Link>

              {dateCreatedFromNow}

{shippingTo}

              {order.shipping_method}

              {grandTotalFormatted}

              {order.payment_method}

              {order.status}

        }
      />
      <Divider />

  )
}

export default OrdersListItem;
<commit_msg>Change order date format<commit_after>import React from 'react';
import { Link } from 'react-router-dom'
import Checkbox from 'material-ui/Checkbox';
import { ListItem } from 'material-ui/List';
import Divider from 'material-ui/Divider';
import FontIcon from 'material-ui/FontIcon';
import messages from 'lib/text'
import * as helper from 'lib/helper'
import style from './style.css'
import moment from 'moment';

const getOrderStateIcons = (order) => {
  let icons = [];

  if(order.hold) {
    icons.push(<FontIcon key="hold" title={messages.orders_hold} style={{ color: 'rgba(0, 0, 0, 0.2)'}} className="material-icons">pause_circle_outline</FontIcon>);
  }

  if(order.paid) {
    icons.push(<FontIcon key="paid" title={messages.orders_paid} style={{ color: 'rgba(251, 184, 41, 1)'}} className="material-icons">monetization_on</FontIcon>);
  }

  if(order.delivered) {
    icons.push(<FontIcon key="delivered" title={messages.orders_delivered} style={{ color: 'rgba(127, 175, 27, 1)'}} className="material-icons">local_shipping</FontIcon>);
  }

  if(order.cancelled) {
    return [<FontIcon key="cancelled" title={messages.orders_cancelled} style={{ color: 'rgba(0, 0, 0, 0.3)'}} className="material-icons">not_interested</FontIcon>];
  }

  if(order.closed) {
    return [<FontIcon key="closed" title={messages.orders_closed} style={{ color: 'rgba(127, 175, 27, 1)'}} className="material-icons">done</FontIcon>];
  }

  if(icons.length === 0 && order.draft){
    icons.unshift(<FontIcon key="draft" title={messages.orders_draft} style={{ color: 'rgba(0, 0, 0, 0.1)'}} className="material-icons">edit</FontIcon>);
  }

  return icons;
}

const OrdersListItem = ({ order, onSelect, selected, settings }) => {
  const checked = selected.includes(order.id);
  let grandTotalFormatted = helper.formatCurrency(order.grand_total, settings);

  const stateIcons = getOrderStateIcons(order);
  const dateCreated = moment(order.date_placed || order.date_created);
  const dateCreatedFromNow = dateCreated.format(`${settings.date_format}`);
  let shippingTo = order.shipping_address ? order.shipping_address.full_name : '';

  return (

      <ListItem style={{ cursor: 'normal' }}
        primaryText={

              <Checkbox checked={checked} onCheck={(event, isInputChecked) => { onSelect(order.id, isInputChecked); }} />

              {stateIcons}

              <Link to={`/admin/order/${order.id}`} className={style.number}>{order.number || 0}</Link>

              {dateCreatedFromNow}

{shippingTo}

              {order.shipping_method}

              {grandTotalFormatted}

              {order.payment_method}

              {order.status}

        }
      />
      <Divider />

  )
}

export default OrdersListItem;
<|endoftext|>


<commit_before>CATARSE.BackersReviewView = Backbone.View.extend({
  initialize: function() {
    var zip_code_valid = null
    var _this = this;
    everything_ok = function(){
      var all_ok = true
      if($('#backer_credits').val() == "false"){
        if(!ok('#user_full_name'))
          all_ok = false
        if(!email_ok())
          all_ok = false
        if(!ok('#user_address_street'))
          all_ok = false
        if(!ok('#user_address_number'))
          all_ok = false
        if(!ok('#user_address_neighbourhood'))
          all_ok = false
        if(!ok('#user_address_city'))
          all_ok = false
      }
      if(!accepted_terms())
        all_ok = false
      if(all_ok){
        _this.updateCurrentBackerInfo();
        $('#user_submit').attr('disabled', false)
        if($('#back_with_credits').length < 1) {
          $('#payment.hide').show();
        }
      } else {
        $('#payment.hide').hide();
        if($('#back_with_credits').length < 1) {
          $('#user_submit').attr('disabled', true)
        }
      }
    }
    ok = function(id){
      var value = $(id).val()
      if(value && value.length > 0){
        $(id).addClass("ok").removeClass("error")
        return true
      } else {
        $(id).addClass("error").removeClass("ok")
        return false
      }
    }
    cpf_ok = function(){
      if($('#user_cpf').isValidCPF()){
        $('#user_cpf').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_cpf').addClass("error").removeClass("ok")
        return false
      }
    }
    email_ok = function(){
      var value = $('#user_email').val()
      var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
      if(value.match(re)){
        $('#user_email').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_email').addClass("error").removeClass("ok")
        return false
      }
    }
    phone_number_ok = function(){
      var value = $('#user_phone_number').val()
      var re = /^\([0-9]{2}\)[0-9]{4}-[0-9]{4}$/
      if(value.match(re)){
        $('#user_phone_number').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_phone_number').addClass("error").removeClass("ok")
        return false
      }
    }
    accepted_terms = function(){
      return $('#accept').is(':checked')
    }
    zip_code_ok = function(){
      if(zip_code_valid){
        $('#user_address_zip_code').addClass("ok").removeClass("error")
        return true
      } else if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').removeClass("error").removeClass("ok")
        return true
      } else {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').addClass("error").removeClass("ok")
        return false
      }
    }
    verify_zip_code = function(){
      zip_code_valid = false
      if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        $('#user_address_zip_code').removeClass("ok").removeClass("error").addClass('loading')
        $.get('/projects/cep/?cep='+$('#user_address_zip_code').val(), function(r){
          $('#user_address_zip_code').removeClass("loading")
          if(r.ok==true){
            zip_code_valid = true
            if(r.street != $('#user_address_street').val()){
              $('#user_address_street').val(r.street).effect("highlight", {}, 1500)
              $('#user_address_number').val(null).effect("highlight", {}, 1500)
              $('#user_address_complement').val(null).effect("highlight", {}, 1500)
              $('#user_address_number').focus()
            }
            if(r.neighbourhood != $('#user_address_neighbourhood').val())
              $('#user_address_neighbourhood').val(r.neighbourhood).effect("highlight", {}, 1500)
            if(r.city != $('#user_address_city').val())
              $('#user_address_city').val(r.city).effect("highlight", {}, 1500)
            if(r.state != $('#user_address_state').val())
              $('#user_address_state').val(r.state).effect("highlight", {}, 1500)
          } else {
            zip_code_valid = false
          }
          everything_ok()
        })
      }
      everything_ok()
    }
    $('#user_cpf').mask("999.999.999-99")
    $('#user_address_zip_code').mask("99999-999")
    $('#user_phone_number').mask("(99)9999-9999")

    $('input[type=text]').keyup(everything_ok)
    $('#user_address_zip_code').keyup(function(){ zip_code_valid = false; everything_ok() })
    $('#accept').click(everything_ok)
    $('select').change(everything_ok)

    $('#international_link').click(function(e){
      e.preventDefault()
      $('#international_link').parent().hide()
      $('#international_expanded').slideDown()
    })
    $('#accept_international').click(function(){
      $('#international_submit').attr('disabled', !$('#accept_international').is(':checked'))
    })

    var can_submit_to_moip = true;

    $('a.payment_link').click(function(event){
      event.preventDefault();
      $('input#payment_method_url').val($(this).data('payment_method_url'));
      if($(this).parent().hasClass('boleto') && can_submit_to_moip) {
        $('form#review_form')[0].submit();
        can_submit_to_moip = false;
      } else if(!$(this).parent().hasClass('boleto')) {
        $('form#review_form')[0].submit();
      }
    });

    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');

    $('.tab_container #payment_menu a').click(function(e){
      $('.payments_type').hide();
      $('.tab_container #payment_menu a').removeClass('selected');
      e.preventDefault();
      var reference = $(e.currentTarget).attr('href');
      var remote_url = $(e.currentTarget).data('target');
      $(this).addClass('selected');
      $(reference).fadeIn(300);
      if($('div', reference).length <= 0) {
        $.get(remote_url, function(response){
          $(reference).empty().html(response);
        });
      }
    });

  },

  updateCurrentBackerInfo: function() {
    var backer_id = $('input#backer_id').val();
    var project_id = $('input#project_id').val();
    var backer_data = {
      payer_name: $('#user_full_name').val(),
      payer_email: $('#user_email').val(),
      address_street: $('#user_address_street').val(),
      address_number: $('#user_address_number').val(),
      address_complement: $('#user_address_complement').val(),
      address_neighbourhood: $('#user_address_neighbourhood').val(),
      address_zip_code: $('#user_address_zip_code').val(),
      address_city: $('#user_address_city').val(),
      address_state: $('#user_address_state').val(),
      address_phone_number: $('#user_phone_number').val()
    }
    $.post('/projects/'+project_id+'/backers/'+backer_id+'/update_info', {
      backer: backer_data
    });
  }
})
<commit_msg>refactored reviews.js and selected first payment method as default<commit_after>CATARSE.BackersReviewView = Backbone.View.extend({
  everything_ok: function(){
    var ok = function(id){
      var value = $(id).val()
      if(value && value.length > 0){
        $(id).addClass("ok").removeClass("error")
        return true
      } else {
        $(id).addClass("error").removeClass("ok")
        return false
      }
    };

    var cpf_ok = function(){
      if($('#user_cpf').isValidCPF()){
        $('#user_cpf').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_cpf').addClass("error").removeClass("ok")
        return false
      }
    };

    var email_ok = function(){
      var value = $('#user_email').val()
      var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
      if(value.match(re)){
        $('#user_email').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_email').addClass("error").removeClass("ok")
        return false
      }
    };

    var phone_number_ok = function(){
      var value = $('#user_phone_number').val()
      var re = /^\([0-9]{2}\)[0-9]{4}-[0-9]{4}$/
      if(value.match(re)){
        $('#user_phone_number').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_phone_number').addClass("error").removeClass("ok")
        return false
      }
    };

    var accepted_terms = function(){
      return $('#accept').is(':checked')
    };

    var zip_code_ok = function(){
      if(zip_code_valid){
        $('#user_address_zip_code').addClass("ok").removeClass("error")
        return true
      } else if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').removeClass("error").removeClass("ok")
        return true
      } else {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').addClass("error").removeClass("ok")
        return false
      }
    };

    var verify_zip_code = function(){
      zip_code_valid = false
      if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        $('#user_address_zip_code').removeClass("ok").removeClass("error").addClass('loading')
        $.get('/projects/cep/?cep='+$('#user_address_zip_code').val(), function(r){
          $('#user_address_zip_code').removeClass("loading")
          if(r.ok==true){
            zip_code_valid = true
            if(r.street != $('#user_address_street').val()){
              $('#user_address_street').val(r.street).effect("highlight", {}, 1500)
              $('#user_address_number').val(null).effect("highlight", {}, 1500)
              $('#user_address_complement').val(null).effect("highlight", {}, 1500)
              $('#user_address_number').focus()
            }
            if(r.neighbourhood != $('#user_address_neighbourhood').val())
              $('#user_address_neighbourhood').val(r.neighbourhood).effect("highlight", {}, 1500)
            if(r.city != $('#user_address_city').val())
              $('#user_address_city').val(r.city).effect("highlight", {}, 1500)
            if(r.state != $('#user_address_state').val())
              $('#user_address_state').val(r.state).effect("highlight", {}, 1500)
          } else {
            zip_code_valid = false
          }
          everything_ok()
        })
      }
      everything_ok()
    };

    var all_ok = true
    if($('#backer_credits').val() == "false"){
      if(!ok('#user_full_name'))
        all_ok = false
      if(!email_ok())
        all_ok = false
      if(!ok('#user_address_street'))
        all_ok = false
      if(!ok('#user_address_number'))
        all_ok = false
      if(!ok('#user_address_neighbourhood'))
        all_ok = false
      if(!ok('#user_address_city'))
        all_ok = false
    }

    if(!accepted_terms()){
      all_ok = false;
    }

    if(all_ok){
      this.updateCurrentBackerInfo();
      $('#user_submit').attr('disabled', false)
      if($('#back_with_credits').length < 1) {
        $('#payment.hide').show();
      }
    } else {
      $('#payment.hide').hide();
      if($('#back_with_credits').length < 1) {
        $('#user_submit').attr('disabled', true)
      }
    }
  },

  events:{
    'keyup input[type=text]' : 'everything_ok',
    'click #accept' : 'everything_ok',
    'change select' : 'everything_ok',
    'keyup #user_address_zip_code' : 'onZipCodeKeyUp',
    'click .tab_container #payment_menu a' : 'onPaymentTabClick'
  },

  onPaymentTabClick: function(e){
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    e.preventDefault();
    var reference = $(e.currentTarget).attr('href');
    var remote_url = $(e.currentTarget).data('target');
    $(e.currentTarget).addClass('selected');
    $(reference).fadeIn(300);
    if($('div', reference).length <= 0) {
      $.get(remote_url, function(response){
        $(reference).empty().html(response);
      });
    }
  },

  onZipCodeKeyUp: function(){
    zip_code_valid = false;
    this.everything_ok()
  },

  initialize: function() {
    var zip_code_valid = null
    var _this = this;

    $('#user_cpf').mask("999.999.999-99")
    $('#user_address_zip_code').mask("99999-999")
    $('#user_phone_number').mask("(99)9999-9999")

    var can_submit_to_moip = true;

    // Here we clean selected tabs and select the first tab by default
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    this.$('.tab_container #payment_menu a:first').trigger('click')
  },

  updateCurrentBackerInfo: function() {
    var backer_id = $('input#backer_id').val();
    var project_id = $('input#project_id').val();
    var backer_data = {
      payer_name: $('#user_full_name').val(),
      payer_email: $('#user_email').val(),
      address_street: $('#user_address_street').val(),
      address_number: $('#user_address_number').val(),
      address_complement: $('#user_address_complement').val(),
      address_neighbourhood: $('#user_address_neighbourhood').val(),
      address_zip_code: $('#user_address_zip_code').val(),
      address_city: $('#user_address_city').val(),
      address_state: $('#user_address_state').val(),
      address_phone_number: $('#user_phone_number').val()
    }
    $.post('/projects/'+project_id+'/backers/'+backer_id+'/update_info', {
      backer: backer_data
    });
  }
})
<|endoftext|>


<commit_before>/**
 * The Form Builder Component
 *
 * @module aui-form-builder
 * @submodule aui-form-builder-field-radio
 */

var L = A.Lang,

    BUILDER = 'builder',
    CHECKED = 'checked',
    CHOICE = 'choice',
    CONTAINER = 'container',
    DISABLED = 'disabled',
    EMPTY_STR = '',
    FIELD = 'field',
    FORM_BUILDER_FIELD = 'form-builder-field',
    FORM_BUILDER_RADIO_FIELD = 'form-builder-radio-field',
    ID = 'id',
    INPUT = 'input',
    NAME = 'name',
    NODE = 'node',
    OPTIONS = 'options',
    PREDEFINED_VALUE = 'predefinedValue',
    RADIO = 'radio',
    SPACE = ' ',
    TEMPLATE_NODE = 'templateNode',

    getCN = A.getClassName,

    CSS_FIELD = getCN(FIELD),
    CSS_FIELD_CHOICE = getCN(FIELD, CHOICE),
    CSS_FIELD_RADIO = getCN(FIELD, RADIO),
    CSS_FORM_BUILDER_FIELD = getCN(FORM_BUILDER_FIELD),
    CSS_FORM_BUILDER_FIELD_NODE = getCN(FORM_BUILDER_FIELD, NODE),
    CSS_FORM_BUILDER_FIELD_OPTIONS_CONTAINER = getCN(FORM_BUILDER_FIELD, OPTIONS, CONTAINER),

    TPL_OPTIONS_CONTAINER = '

',
    TPL_RADIO =
        '
<input id="{id}" class="' + [CSS_FIELD, CSS_FIELD_CHOICE, CSS_FIELD_RADIO, CSS_FORM_BUILDER_FIELD_NODE].join(
            SPACE) +
        '" name="{name}" type="radio" value="{value}" {checked} {disabled} />{label}
';

/**
 * A base class for FormBuilderRadioField.
 *
 * @class A.FormBuilderRadioField
 * @extends A.FormBuilderMultipleChoiceField
 * @param config {Object} Object literal specifying widget configuration properties.
 * @constructor
 */
var FormBuilderRadioField = A.Component.create({

    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: FORM_BUILDER_RADIO_FIELD,

    /**
     * Static property used to define the default attribute
     * configuration for the FormBuilderRadioField.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * The predefined value for the radio fields.
         *
         * @attribute predefinedValue
         */
        predefinedValue: {
            valueFn: '_valuePredefinedValueFn'
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @attribute template
         */
        template: {
            valueFn: function() {
                return TPL_RADIO;
            }
        }

    },

    /**
     * TODO. Wanna help? Please send a Pull Request.
     *
     * @property CSS_PREFIX
     * @type String
     * @static
     */
    CSS_PREFIX: CSS_FORM_BUILDER_FIELD,

    /**
     * Static property used to define which component it extends.
     *
     * @property EXTENDS
     * @type Object
     * @static
     */
    EXTENDS: A.FormBuilderMultipleChoiceField,

    prototype: {

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method getHTML
         */
        getHTML: function() {
            return TPL_OPTIONS_CONTAINER;
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetDisabled
         * @param val
         * @protected
         */
        _uiSetDisabled: function(val) {
            var instance = this,
                templateNode = instance.get(TEMPLATE_NODE);

            templateNode.all(INPUT).each(function(input) {
                if (val) {
                    input.setAttribute(DISABLED, val);
                }
                else {
                    input.removeAttribute(DISABLED);
                }
            });
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetOptions
         * @param val
         * @protected
         */
        _uiSetOptions: function(val) {
            var instance = this,
                buffer = [],
                counter = 0,
                hasPredefinedValue = false,
                predefinedValue = instance.get(PREDEFINED_VALUE),
                templateNode = instance.get(TEMPLATE_NODE);

            A.each(val, function(item, index, collection) {
                var checked = A.Array.indexOf(predefinedValue, item.value) > -1;

                buffer.push(
                    L.sub(
                        TPL_RADIO, {
                            checked: checked ? 'checked="checked"' : EMPTY_STR,
                            disabled: instance.get(DISABLED) ? 'disabled="disabled"' : EMPTY_STR,
                            id: instance.get(ID) + counter++,
                            label: item.label,
                            name: instance.get(NAME),
                            value: item.value
                        }
                    )
                );

                 if (checked) {
                    hasPredefinedValue = true;
                }
            });

            instance.optionNodes = A.NodeList.create(buffer.join(EMPTY_STR));

            templateNode.setContent(instance.optionNodes);

            if (!hasPredefinedValue) {
                instance.set(PREDEFINED_VALUE, instance._valuePredefinedValueFn());

                instance.get(BUILDER).editField(instance);
            }
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetPredefinedValue
         * @param val
         * @protected
         */
        _uiSetPredefinedValue: function(val) {
            var instance = this,
                optionNodes = instance.optionNodes;

            if (!optionNodes) {
                return;
            }

            optionNodes.set(CHECKED, false);

            optionNodes.all('input[value="' + val + '"]').set(CHECKED, true);
        },

        /**
         * Returns the first option value if no predefined value is specified.
         *
         * @method _valuePredefinedValueFn
         * @protected
         */
        _valuePredefinedValueFn: function() {
            var instance = this,
                options = instance.get(OPTIONS),
                predefinedValue;

            if (options.length) {
                predefinedValue = options[0].value;
            }

            return predefinedValue;
        }

    }

});

A.FormBuilderRadioField = FormBuilderRadioField;

A.FormBuilder.types.radio = A.FormBuilderRadioField;
<commit_msg>AUI-1034 Source formatting<commit_after>/**
 * The Form Builder Component
 *
 * @module aui-form-builder
 * @submodule aui-form-builder-field-radio
 */

var L = A.Lang,

    BUILDER = 'builder',
    CHECKED = 'checked',
    CHOICE = 'choice',
    CONTAINER = 'container',
    DISABLED = 'disabled',
    EMPTY_STR = '',
    FIELD = 'field',
    FORM_BUILDER_FIELD = 'form-builder-field',
    FORM_BUILDER_RADIO_FIELD = 'form-builder-radio-field',
    ID = 'id',
    INPUT = 'input',
    NAME = 'name',
    NODE = 'node',
    OPTIONS = 'options',
    PREDEFINED_VALUE = 'predefinedValue',
    RADIO = 'radio',
    SPACE = ' ',
    TEMPLATE_NODE = 'templateNode',

    getCN = A.getClassName,

    CSS_FIELD = getCN(FIELD),
    CSS_FIELD_CHOICE = getCN(FIELD, CHOICE),
    CSS_FIELD_RADIO = getCN(FIELD, RADIO),
    CSS_FORM_BUILDER_FIELD = getCN(FORM_BUILDER_FIELD),
    CSS_FORM_BUILDER_FIELD_NODE = getCN(FORM_BUILDER_FIELD, NODE),
    CSS_FORM_BUILDER_FIELD_OPTIONS_CONTAINER = getCN(FORM_BUILDER_FIELD, OPTIONS, CONTAINER),

    TPL_OPTIONS_CONTAINER = '

',
    TPL_RADIO =
        '
<input id="{id}" class="' + [CSS_FIELD, CSS_FIELD_CHOICE, CSS_FIELD_RADIO, CSS_FORM_BUILDER_FIELD_NODE].join(
            SPACE) +
        '" name="{name}" type="radio" value="{value}" {checked} {disabled} />{label}
';

/**
 * A base class for FormBuilderRadioField.
 *
 * @class A.FormBuilderRadioField
 * @extends A.FormBuilderMultipleChoiceField
 * @param config {Object} Object literal specifying widget configuration properties.
 * @constructor
 */
var FormBuilderRadioField = A.Component.create({

    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: FORM_BUILDER_RADIO_FIELD,

    /**
     * Static property used to define the default attribute
     * configuration for the FormBuilderRadioField.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * The predefined value for the radio fields.
         *
         * @attribute predefinedValue
         */
        predefinedValue: {
            valueFn: '_valuePredefinedValueFn'
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @attribute template
         */
        template: {
            valueFn: function() {
                return TPL_RADIO;
            }
        }

    },

    /**
     * TODO. Wanna help? Please send a Pull Request.
     *
     * @property CSS_PREFIX
     * @type String
     * @static
     */
    CSS_PREFIX: CSS_FORM_BUILDER_FIELD,

    /**
     * Static property used to define which component it extends.
     *
     * @property EXTENDS
     * @type Object
     * @static
     */
    EXTENDS: A.FormBuilderMultipleChoiceField,

    prototype: {

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method getHTML
         */
        getHTML: function() {
            return TPL_OPTIONS_CONTAINER;
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetDisabled
         * @param val
         * @protected
         */
        _uiSetDisabled: function(val) {
            var instance = this,
                templateNode = instance.get(TEMPLATE_NODE);

            templateNode.all(INPUT).each(function(input) {
                if (val) {
                    input.setAttribute(DISABLED, val);
                }
                else {
                    input.removeAttribute(DISABLED);
                }
            });
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetOptions
         * @param val
         * @protected
         */
        _uiSetOptions: function(val) {
            var instance = this,
                buffer = [],
                counter = 0,
                hasPredefinedValue = false,
                predefinedValue = instance.get(PREDEFINED_VALUE),
                templateNode = instance.get(TEMPLATE_NODE);

            A.each(val, function(item, index, collection) {
                var checked = A.Array.indexOf(predefinedValue, item.value) > -1;

                buffer.push(
                    L.sub(
                        TPL_RADIO, {
                            checked: checked ? 'checked="checked"' : EMPTY_STR,
                            disabled: instance.get(DISABLED) ? 'disabled="disabled"' : EMPTY_STR,
                            id: instance.get(ID) + counter++,
                            label: item.label,
                            name: instance.get(NAME),
                            value: item.value
                        }
                    )
                );

                if (checked) {
                    hasPredefinedValue = true;
                }
            });

            instance.optionNodes = A.NodeList.create(buffer.join(EMPTY_STR));

            templateNode.setContent(instance.optionNodes);

            if (!hasPredefinedValue) {
                instance.set(PREDEFINED_VALUE, instance._valuePredefinedValueFn());

                instance.get(BUILDER).editField(instance);
            }
        },

        /**
         * TODO. Wanna help? Please send a Pull Request.
         *
         * @method _uiSetPredefinedValue
         * @param val
         * @protected
         */
        _uiSetPredefinedValue: function(val) {
            var instance = this,
                optionNodes = instance.optionNodes;

            if (!optionNodes) {
                return;
            }

            optionNodes.set(CHECKED, false);

            optionNodes.all('input[value="' + val + '"]').set(CHECKED, true);
        },

        /**
         * Returns the first option value if no predefined value is specified.
         *
         * @method _valuePredefinedValueFn
         * @protected
         */
        _valuePredefinedValueFn: function() {
            var instance = this,
                options = instance.get(OPTIONS),
                predefinedValue;

            if (options.length) {
                predefinedValue = options[0].value;
            }

            return predefinedValue;
        }

    }

});

A.FormBuilderRadioField = FormBuilderRadioField;

A.FormBuilder.types.radio = A.FormBuilderRadioField;
<|endoftext|>


<commit_before>'use strict';

import React from 'react';

class UsersActivityData extends React.Component {

  componentWillMount() {
    this.props.setUsersActivityData(this.props.data);
  }

  render() {
    const title = this.props.data && this.props.data.split('-').join(' ');
    const users = this.props.usersActivityData ? this.props.usersActivityData.users : {};
    console.log()
    return (

{title}

          { Object.keys(users).map( (user, i) => {
            return (

                { title === "ranking" && {i+1}	 }
                {users[user].name}
                {users[user].total} roads

            );
          })}

    );
  }
}

export default UsersActivityData;
<commit_msg>ranking table sort<commit_after>'use strict';

import React from 'react';

class UsersActivityData extends React.Component {

  componentWillMount() {
    this.props.setUsersActivityData(this.props.data);
  }

  render() {
    const title = this.props.data && this.props.data.split('-').join(' ');
    const users = this.props.usersActivityData ? this.props.usersActivityData.users : {};

    var sortable = [];
    for (var user in users)
      sortable.push(users[user])
      sortable.sort(
      function(a, b) {
        return a.total - b.total
      }
    )

    return (

{title}

          { sortable.reverse().map( (user, i) => {
            return (

                { title === "ranking" && {i+1}	 }
                {user.name}
                {user.total} roads

            );
          })}

    );
  }
}

export default UsersActivityData;
<|endoftext|>


<commit_before>Package.describe({
  name: "shell-server",
  version: "0.2.3",
  summary: "Server-side component of the `meteor shell` command.",
  documentation: "README.md"
});

Package.onUse(function(api) {
  api.use("ecmascript", "server");
  api.mainModule("main.js", "server");
});
<commit_msg>Bump shell-server package version to 0.2.4.<commit_after>Package.describe({
  name: "shell-server",
  version: "0.2.4",
  summary: "Server-side component of the `meteor shell` command.",
  documentation: "README.md"
});

Package.onUse(function(api) {
  api.use("ecmascript", "server");
  api.mainModule("main.js", "server");
});
<|endoftext|>


<commit_before>/*global Mousetrap:true */
import loadScript from 'discourse/lib/load-script';
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
import { showSelector } from "discourse/lib/emoji/emoji-toolbar";

// Our head can be a static string or a function that returns a string
// based on input (like for numbered lists).
function getHead(head, prev) {
  if (typeof head === "string") {
    return [head, head.length];
  } else {
    return getHead(head(prev));
  }
}

const _createCallbacks = [];

function Toolbar() {
  this.shortcuts = {};

  this.groups = [
    {group: 'fontStyles', buttons: []},
    {group: 'insertions', buttons: []},
    {group: 'extras', buttons: [], lastGroup: true}
  ];

  this.addButton({
    id: 'bold',
    group: 'fontStyles',
    shortcut: 'B',
    perform: e => e.applySurround('**', '**', 'bold_text')
  });

  this.addButton({
    id: 'italic',
    group: 'fontStyles',
    shortcut: 'I',
    perform: e => e.applySurround('*', '*', 'italic_text')
  });

  this.addButton({id: 'link', group: 'insertions', shortcut: 'K', action: 'showLinkModal'});

  this.addButton({
    id: 'quote',
    group: 'insertions',
    icon: 'quote-right',
    shortcut: 'Shift+9',
    perform: e => e.applySurround('> ', '', 'code_text')
  });

  this.addButton({
    id: 'code',
    group: 'insertions',
    shortcut: 'Shift+C',
    perform(e) {
      if (e.selected.value.indexOf("\n") !== -1) {
        e.applySurround('    ', '', 'code_text');
      } else {
        e.applySurround('`', '`', 'code_text');
      }
    },
  });

  this.addButton({
    id: 'bullet',
    group: 'extras',
    icon: 'list-ul',
    shortcut: 'Shift+8',
    title: 'composer.ulist_title',
    perform: e => e.applyList('* ', 'list_item')
  });

  this.addButton({
    id: 'list',
    group: 'extras',
    icon: 'list-ol',
    shortcut: 'Shift+7',
    title: 'composer.olist_title',
    perform: e => e.applyList(i => !i ? "1. " : `${parseInt(i) + 1}. `, 'list_item')
  });

  this.addButton({
    id: 'heading',
    group: 'extras',
    icon: 'font',
    shortcut: 'Alt+1',
    perform: e => e.applyList('## ', 'heading_text')
  });

  this.addButton({
    id: 'rule',
    group: 'extras',
    icon: 'minus',
    shortcut: 'Alt+R',
    title: 'composer.hr_title',
    perform: e => e.addText("\n\n----------\n")
  });
};

Toolbar.prototype.addButton = function(button) {
  const g = this.groups.findProperty('group', button.group);
  if (!g) {
    throw `Couldn't find toolbar group ${button.group}`;
  }

  const createdButton = {
    id: button.id,
    className: button.className || button.id,
    icon: button.icon || button.id,
    action: button.action || 'toolbarButton',
    perform: button.perform || Ember.K
  };

  if (button.sendAction) {
    createdButton.sendAction = button.sendAction;
  }

  const title = I18n.t(button.title || `composer.${button.id}_title`);
  if (button.shortcut) {
    const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
    const mod = mac ? 'Meta' : 'Ctrl';
    createdButton.title = `${title} (${mod}+${button.shortcut})`;

    // Mac users are used to glyphs for shortcut keys
    if (mac) {
      createdButton.title = createdButton.title.replace('Shift', "\u21E7")
                                               .replace('Meta', "\u2318")
                                               .replace('Alt', "\u2325")
                                               .replace(/\+/g, '');
    }

    this.shortcuts[`${mod}+${button.shortcut}`.toLowerCase()] = createdButton;
  } else {
    createdButton.title = title;
  }

  if (button.unshift) {
    g.buttons.unshift(createdButton);
  } else {
    g.buttons.push(createdButton);
  }
};

export function onToolbarCreate(func) {
  _createCallbacks.push(func);
};

export default Ember.Component.extend({
  classNames: ['d-editor'],
  ready: false,
  insertLinkHidden: true,
  link: '',
  lastSel: null,

  @computed('placeholder')
  placeholderTranslated(placeholder) {
    if (placeholder) return I18n.t(placeholder);
    return null;
  },

  @on('didInsertElement')
  _startUp() {
    this._applyEmojiAutocomplete();

    loadScript('defer/html-sanitizer-bundle').then(() => this.set('ready', true));

    const shortcuts = this.get('toolbar.shortcuts');
    Ember.keys(shortcuts).forEach(sc => {
      const button = shortcuts[sc];
      Mousetrap(this.$('.d-editor-input')[0]).bind(sc, () => {
        this.send(button.action, button);
      });
    });

    // disable clicking on links in the preview
    this.$('.d-editor-preview').on('click.preview', e => {
      e.preventDefault();
      return false;
    });

    this.appEvents.on('composer:insert-text', text => {
      this._addText(this._getSelected(), text);
    });
  },

  @on('willDestroyElement')
  _shutDown() {
    this.appEvents.off('composer:insert-text');

    Ember.keys(this.get('toolbar.shortcuts')).forEach(sc => {
      Mousetrap(this.$('.d-editor-input')[0]).unbind(sc);
    });
    this.$('.d-editor-preview').off('click.preview');
  },

  @computed
  toolbar() {
    const toolbar = new Toolbar();
    _createCallbacks.forEach(cb => cb(toolbar));
    this.sendAction('extraButtons', toolbar);
    return toolbar;
  },

  _updatePreview() {
    const value = this.get('value');
    const markdownOptions = this.get('markdownOptions') || {};
    markdownOptions.sanitize = true;

    this.set('preview', Discourse.Dialect.cook(value || "", markdownOptions));
    Ember.run.scheduleOnce('afterRender', () => {
      if (this._state !== "inDOM") { return; }
      const $preview = this.$('.d-editor-preview');
      if ($preview.length === 0) return;

      this.sendAction('previewUpdated', $preview);
    });
  },

  @observes('ready', 'value')
  _watchForChanges() {
    if (!this.get('ready')) { return; }
    Ember.run.debounce(this, this._updatePreview, 30);
  },

  _applyEmojiAutocomplete() {
    if (!this.siteSettings.enable_emoji) { return; }

    const container = this.container;
    const template = container.lookup('template:emoji-selector-autocomplete.raw');
    const self = this;

    this.$('.d-editor-input').autocomplete({
      template: template,
      key: ":",

      transformComplete(v) {
        if (v.code) {
          return `${v.code}:`;
        } else {
          showSelector({
            appendTo: self.$(),
            container,
            onSelect: title => self._addText(this._getSelected(), `${title}:`)
          });
          return "";
        }
      },

      dataSource(term) {
        return new Ember.RSVP.Promise(resolve => {
          const full = `:${term}`;
          term = term.toLowerCase();

          if (term === "") {
            return resolve(["smile", "smiley", "wink", "sunny", "blush"]);
          }

          if (Discourse.Emoji.translations[full]) {
            return resolve([Discourse.Emoji.translations[full]]);
          }

          const options = Discourse.Emoji.search(term, {maxResults: 5});

          return resolve(options);
        }).then(list => list.map(code => {
          return {code, src: Discourse.Emoji.urlFor(code)};
        })).then(list => {
          if (list.length) {
            list.push({ label: I18n.t("composer.more_emoji") });
          }
          return list;
        });
      }
    });
  },

  _getSelected() {
    if (!this.get('ready')) { return; }

    const textarea = this.$('textarea.d-editor-input')[0];
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    const value = textarea.value.substring(start, end);
    const pre = textarea.value.slice(0, start);
    const post = textarea.value.slice(end);

    return { start, end, value, pre, post };
  },

  _selectText(from, length) {
    Ember.run.scheduleOnce('afterRender', () => {
      const textarea = this.$('textarea.d-editor-input')[0];
      textarea.focus();
      textarea.selectionStart = from;
      textarea.selectionEnd = textarea.selectionStart + length;
    });
  },

  _applySurround(sel, head, tail, exampleKey) {
    const pre = sel.pre;
    const post = sel.post;

    const tlen = tail.length;
    if (sel.start === sel.end) {
      if (tlen === 0) { return; }

      const [hval, hlen] = getHead(head);
      const example = I18n.t(`composer.${exampleKey}`);
      this.set('value', `${pre}${hval}${example}${tail}${post}`);
      this._selectText(pre.length + hlen, example.length);
    } else {
      const lines = sel.value.split("\n");

      let [hval, hlen] = getHead(head);
      if (lines.length === 1 && pre.slice(-tlen) === tail && post.slice(0, hlen) === hval) {
        this.set('value', `${pre.slice(0, -hlen)}${sel.value}${post.slice(tlen)}`);
        this._selectText(sel.start - hlen, sel.value.length);
      } else {
        const contents = lines.map(l => {
          if (l.length === 0) { return l; }

          if (l.slice(0, hlen) === hval && tlen === 0 || l.slice(-tlen) === tail) {
            if (tlen === 0) {
              const result = l.slice(hlen);
              [hval, hlen] = getHead(head, hval);
              return result;
            } else if (l.slice(-tlen) === tail) {
              const result = l.slice(hlen, -tlen);
              [hval, hlen] = getHead(head, hval);
              return result;
            }
          }
          const result = `${hval}${l}${tail}`;
          [hval, hlen] = getHead(head, hval);
          return result;
        }).join("\n");

        this.set('value', `${pre}${contents}${post}`);
        if (lines.length === 1 && tlen > 0) {
          this._selectText(sel.start + hlen, contents.length - hlen - hlen);
        } else {
          this._selectText(sel.start, contents.length);
        }
      }
    }
  },

  _applyList(sel, head, exampleKey) {
    if (sel.value.indexOf("\n") !== -1) {
      this._applySurround(sel, head, '', exampleKey);
    } else {

      const [hval, hlen] = getHead(head);
      if (sel.start === sel.end) {
        sel.value = I18n.t(`composer.${exampleKey}`);
      }

      const trimmedPre = sel.pre.trim();
      const number = (sel.value.indexOf(hval) === 0) ? sel.value.slice(hlen) : `${hval}${sel.value}`;
      const preLines = trimmedPre.length ? `${trimmedPre}\n\n` : "";

      const trimmedPost = sel.post.trim();
      const post = trimmedPost.length ? `\n\n${trimmedPost}` : trimmedPost;

      this.set('value', `${preLines}${number}${post}`);
      this._selectText(preLines.length, number.length);
    }
  },

  _addText(sel, text) {
    const insert = `${sel.pre}${text}`;
    this.set('value', `${insert}${sel.post}`);
    this._selectText(insert.length, 0);
  },

  actions: {
    toolbarButton(button) {
      const selected = this._getSelected();
      const toolbarEvent = {
        selected,
        applySurround: (head, tail, exampleKey) => this._applySurround(selected, head, tail, exampleKey),
        applyList: (head, exampleKey) => this._applyList(selected, head, exampleKey),
        addText: text => this._addText(selected, text)
      };

      if (button.sendAction) {
        return this.sendAction(button.sendAction, toolbarEvent);
      } else {
        button.perform(toolbarEvent);
      }
    },

    showLinkModal() {
      this._lastSel = this._getSelected();
      this.set('insertLinkHidden', false);
    },

    insertLink() {
      const link = this.get('link');

      if (Ember.isEmpty(link)) { return; }
      const m = / "([^"]+)"/.exec(link);
      if (m && m.length === 2) {
        const description = m[1];
        const remaining = link.replace(m[0], '');
        this._addText(this._lastSel, `[${description}](${remaining})`);
      } else {
        const selectedValue = this._lastSel.value || link;
        this._addText(this._lastSel, `[${selectedValue}](${link})`);
      }

      this.set('link', '');
    },

    emoji() {
      showSelector({
        appendTo: this.$(),
        container: this.container,
        onSelect: title => this._addText(this._getSelected(), `:${title}:`)
      });
    }
  }

});
<commit_msg>FIX: Don't scroll to the bottom when inserting in the middle<commit_after>/*global Mousetrap:true */
import loadScript from 'discourse/lib/load-script';
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
import { showSelector } from "discourse/lib/emoji/emoji-toolbar";

// Our head can be a static string or a function that returns a string
// based on input (like for numbered lists).
function getHead(head, prev) {
  if (typeof head === "string") {
    return [head, head.length];
  } else {
    return getHead(head(prev));
  }
}

const _createCallbacks = [];

function Toolbar() {
  this.shortcuts = {};

  this.groups = [
    {group: 'fontStyles', buttons: []},
    {group: 'insertions', buttons: []},
    {group: 'extras', buttons: [], lastGroup: true}
  ];

  this.addButton({
    id: 'bold',
    group: 'fontStyles',
    shortcut: 'B',
    perform: e => e.applySurround('**', '**', 'bold_text')
  });

  this.addButton({
    id: 'italic',
    group: 'fontStyles',
    shortcut: 'I',
    perform: e => e.applySurround('*', '*', 'italic_text')
  });

  this.addButton({id: 'link', group: 'insertions', shortcut: 'K', action: 'showLinkModal'});

  this.addButton({
    id: 'quote',
    group: 'insertions',
    icon: 'quote-right',
    shortcut: 'Shift+9',
    perform: e => e.applySurround('> ', '', 'code_text')
  });

  this.addButton({
    id: 'code',
    group: 'insertions',
    shortcut: 'Shift+C',
    perform(e) {
      if (e.selected.value.indexOf("\n") !== -1) {
        e.applySurround('    ', '', 'code_text');
      } else {
        e.applySurround('`', '`', 'code_text');
      }
    },
  });

  this.addButton({
    id: 'bullet',
    group: 'extras',
    icon: 'list-ul',
    shortcut: 'Shift+8',
    title: 'composer.ulist_title',
    perform: e => e.applyList('* ', 'list_item')
  });

  this.addButton({
    id: 'list',
    group: 'extras',
    icon: 'list-ol',
    shortcut: 'Shift+7',
    title: 'composer.olist_title',
    perform: e => e.applyList(i => !i ? "1. " : `${parseInt(i) + 1}. `, 'list_item')
  });

  this.addButton({
    id: 'heading',
    group: 'extras',
    icon: 'font',
    shortcut: 'Alt+1',
    perform: e => e.applyList('## ', 'heading_text')
  });

  this.addButton({
    id: 'rule',
    group: 'extras',
    icon: 'minus',
    shortcut: 'Alt+R',
    title: 'composer.hr_title',
    perform: e => e.addText("\n\n----------\n")
  });
};

Toolbar.prototype.addButton = function(button) {
  const g = this.groups.findProperty('group', button.group);
  if (!g) {
    throw `Couldn't find toolbar group ${button.group}`;
  }

  const createdButton = {
    id: button.id,
    className: button.className || button.id,
    icon: button.icon || button.id,
    action: button.action || 'toolbarButton',
    perform: button.perform || Ember.K
  };

  if (button.sendAction) {
    createdButton.sendAction = button.sendAction;
  }

  const title = I18n.t(button.title || `composer.${button.id}_title`);
  if (button.shortcut) {
    const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
    const mod = mac ? 'Meta' : 'Ctrl';
    createdButton.title = `${title} (${mod}+${button.shortcut})`;

    // Mac users are used to glyphs for shortcut keys
    if (mac) {
      createdButton.title = createdButton.title.replace('Shift', "\u21E7")
                                               .replace('Meta', "\u2318")
                                               .replace('Alt', "\u2325")
                                               .replace(/\+/g, '');
    }

    this.shortcuts[`${mod}+${button.shortcut}`.toLowerCase()] = createdButton;
  } else {
    createdButton.title = title;
  }

  if (button.unshift) {
    g.buttons.unshift(createdButton);
  } else {
    g.buttons.push(createdButton);
  }
};

export function onToolbarCreate(func) {
  _createCallbacks.push(func);
};

export default Ember.Component.extend({
  classNames: ['d-editor'],
  ready: false,
  insertLinkHidden: true,
  link: '',
  lastSel: null,

  @computed('placeholder')
  placeholderTranslated(placeholder) {
    if (placeholder) return I18n.t(placeholder);
    return null;
  },

  @on('didInsertElement')
  _startUp() {
    this._applyEmojiAutocomplete();

    loadScript('defer/html-sanitizer-bundle').then(() => this.set('ready', true));

    const shortcuts = this.get('toolbar.shortcuts');
    Ember.keys(shortcuts).forEach(sc => {
      const button = shortcuts[sc];
      Mousetrap(this.$('.d-editor-input')[0]).bind(sc, () => {
        this.send(button.action, button);
      });
    });

    // disable clicking on links in the preview
    this.$('.d-editor-preview').on('click.preview', e => {
      e.preventDefault();
      return false;
    });

    this.appEvents.on('composer:insert-text', text => {
      this._addText(this._getSelected(), text);
    });
  },

  @on('willDestroyElement')
  _shutDown() {
    this.appEvents.off('composer:insert-text');

    Ember.keys(this.get('toolbar.shortcuts')).forEach(sc => {
      Mousetrap(this.$('.d-editor-input')[0]).unbind(sc);
    });
    this.$('.d-editor-preview').off('click.preview');
  },

  @computed
  toolbar() {
    const toolbar = new Toolbar();
    _createCallbacks.forEach(cb => cb(toolbar));
    this.sendAction('extraButtons', toolbar);
    return toolbar;
  },

  _updatePreview() {
    const value = this.get('value');
    const markdownOptions = this.get('markdownOptions') || {};
    markdownOptions.sanitize = true;

    this.set('preview', Discourse.Dialect.cook(value || "", markdownOptions));
    Ember.run.scheduleOnce('afterRender', () => {
      if (this._state !== "inDOM") { return; }
      const $preview = this.$('.d-editor-preview');
      if ($preview.length === 0) return;

      this.sendAction('previewUpdated', $preview);
    });
  },

  @observes('ready', 'value')
  _watchForChanges() {
    if (!this.get('ready')) { return; }
    Ember.run.debounce(this, this._updatePreview, 30);
  },

  _applyEmojiAutocomplete() {
    if (!this.siteSettings.enable_emoji) { return; }

    const container = this.container;
    const template = container.lookup('template:emoji-selector-autocomplete.raw');
    const self = this;

    this.$('.d-editor-input').autocomplete({
      template: template,
      key: ":",

      transformComplete(v) {
        if (v.code) {
          return `${v.code}:`;
        } else {
          showSelector({
            appendTo: self.$(),
            container,
            onSelect: title => self._addText(this._getSelected(), `${title}:`)
          });
          return "";
        }
      },

      dataSource(term) {
        return new Ember.RSVP.Promise(resolve => {
          const full = `:${term}`;
          term = term.toLowerCase();

          if (term === "") {
            return resolve(["smile", "smiley", "wink", "sunny", "blush"]);
          }

          if (Discourse.Emoji.translations[full]) {
            return resolve([Discourse.Emoji.translations[full]]);
          }

          const options = Discourse.Emoji.search(term, {maxResults: 5});

          return resolve(options);
        }).then(list => list.map(code => {
          return {code, src: Discourse.Emoji.urlFor(code)};
        })).then(list => {
          if (list.length) {
            list.push({ label: I18n.t("composer.more_emoji") });
          }
          return list;
        });
      }
    });
  },

  _getSelected() {
    if (!this.get('ready')) { return; }

    const textarea = this.$('textarea.d-editor-input')[0];
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    const value = textarea.value.substring(start, end);
    const pre = textarea.value.slice(0, start);
    const post = textarea.value.slice(end);

    return { start, end, value, pre, post };
  },

  _selectText(from, length) {
    Ember.run.scheduleOnce('afterRender', () => {
      const textarea = this.$('textarea.d-editor-input')[0];
      textarea.selectionStart = from;
      textarea.selectionEnd = textarea.selectionStart + length;
    });
  },

  _applySurround(sel, head, tail, exampleKey) {
    const pre = sel.pre;
    const post = sel.post;

    const tlen = tail.length;
    if (sel.start === sel.end) {
      if (tlen === 0) { return; }

      const [hval, hlen] = getHead(head);
      const example = I18n.t(`composer.${exampleKey}`);
      this.set('value', `${pre}${hval}${example}${tail}${post}`);
      this._selectText(pre.length + hlen, example.length);
    } else {
      const lines = sel.value.split("\n");

      let [hval, hlen] = getHead(head);
      if (lines.length === 1 && pre.slice(-tlen) === tail && post.slice(0, hlen) === hval) {
        this.set('value', `${pre.slice(0, -hlen)}${sel.value}${post.slice(tlen)}`);
        this._selectText(sel.start - hlen, sel.value.length);
      } else {
        const contents = lines.map(l => {
          if (l.length === 0) { return l; }

          if (l.slice(0, hlen) === hval && tlen === 0 || l.slice(-tlen) === tail) {
            if (tlen === 0) {
              const result = l.slice(hlen);
              [hval, hlen] = getHead(head, hval);
              return result;
            } else if (l.slice(-tlen) === tail) {
              const result = l.slice(hlen, -tlen);
              [hval, hlen] = getHead(head, hval);
              return result;
            }
          }
          const result = `${hval}${l}${tail}`;
          [hval, hlen] = getHead(head, hval);
          return result;
        }).join("\n");

        this.set('value', `${pre}${contents}${post}`);
        if (lines.length === 1 && tlen > 0) {
          this._selectText(sel.start + hlen, contents.length - hlen - hlen);
        } else {
          this._selectText(sel.start, contents.length);
        }
      }
    }
  },

  _applyList(sel, head, exampleKey) {
    if (sel.value.indexOf("\n") !== -1) {
      this._applySurround(sel, head, '', exampleKey);
    } else {

      const [hval, hlen] = getHead(head);
      if (sel.start === sel.end) {
        sel.value = I18n.t(`composer.${exampleKey}`);
      }

      const trimmedPre = sel.pre.trim();
      const number = (sel.value.indexOf(hval) === 0) ? sel.value.slice(hlen) : `${hval}${sel.value}`;
      const preLines = trimmedPre.length ? `${trimmedPre}\n\n` : "";

      const trimmedPost = sel.post.trim();
      const post = trimmedPost.length ? `\n\n${trimmedPost}` : trimmedPost;

      this.set('value', `${preLines}${number}${post}`);
      this._selectText(preLines.length, number.length);
    }
  },

  _addText(sel, text) {
    const insert = `${sel.pre}${text}`;
    this.set('value', `${insert}${sel.post}`);
    this._selectText(insert.length, 0);
  },

  actions: {
    toolbarButton(button) {
      const selected = this._getSelected();
      const toolbarEvent = {
        selected,
        applySurround: (head, tail, exampleKey) => this._applySurround(selected, head, tail, exampleKey),
        applyList: (head, exampleKey) => this._applyList(selected, head, exampleKey),
        addText: text => this._addText(selected, text)
      };

      if (button.sendAction) {
        return this.sendAction(button.sendAction, toolbarEvent);
      } else {
        button.perform(toolbarEvent);
      }
    },

    showLinkModal() {
      this._lastSel = this._getSelected();
      this.set('insertLinkHidden', false);
    },

    insertLink() {
      const link = this.get('link');

      if (Ember.isEmpty(link)) { return; }
      const m = / "([^"]+)"/.exec(link);
      if (m && m.length === 2) {
        const description = m[1];
        const remaining = link.replace(m[0], '');
        this._addText(this._lastSel, `[${description}](${remaining})`);
      } else {
        const selectedValue = this._lastSel.value || link;
        this._addText(this._lastSel, `[${selectedValue}](${link})`);
      }

      this.set('link', '');
    },

    emoji() {
      showSelector({
        appendTo: this.$(),
        container: this.container,
        onSelect: title => this._addText(this._getSelected(), `:${title}:`)
      });
    }
  }

});
<|endoftext|>


<commit_before>/*
 * @package jsDAV
 * @subpackage DAVACL
 * @copyright Copyright(c) 2011 Tri Tech Computers Ltd. <info AT tri-tech DOT com>
 * @author James Emerton <james AT tri-tech DOT com>
 * @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
 */

var Exc = require("./../../DAV/exceptions");
var Util = require("./../../DAV/util");

var jsDAV_Property = require("./../../DAV/property").jsDAV_Property;
var jsDAV_Property_Href = require("./../../DAV/property/href").jsDAV_Property_Href;

function jsDAV_Property_Principal(type, href) {
    this.type = type;
    if (type === jsDAV_Property_Principal.HREF && href === undefined) {
        throw new Exc.jsDAV_Exception('The href argument must be specified for the HREF principal type.');
    }
    this.href = href;
}

(function() {

    /**
     * To specify a not-logged-in user, use the UNAUTHENTICTED principal
     */
    this.UNAUTHENTICATED = 1;

    /**
     * To specify any principal that is logged in, use AUTHENTICATED
     */
    this.AUTHENTICATED = 2;

    /**
     * Specific principals can be specified with the HREF
     */
    this.HREF = 3;

    /**
     * Everybody, basically
     */
    this.ALL = 4;

    /**
     * Returns the principal type
     *
     * @return int
     */
    this.getType = function() {
        return this.type;
    }

    /**
     * Returns the principal uri.
     *
     * @return string
     */
    this.getHref = function() {
        return this.href;
    }

    this.serialize = function(handler, lmDom) {
        switch(this.type) {
            case jsDAV_Property_Principal.UNAUTHENTICATED:
                return lmDom+'<d:unauthenticated/>';

            case jsDAV_Property_Principal.AUTHENTICATED:
                return lmDom+'<d:authenticated/>';

            case jsDAV_Property_Principal.HREF:
                var href = new jsDAV_Property_Href(this.href, true);
                return href.serialize(handler, lmDom);
        }
    }

    /**
     * Deserializes a DOM element into a property object.
     *
     * @param DOMElement $dom
     * @return Sabre_DAV_Property_Principal
     */
    this.unserialize = function(dom) {
        var parentNode = dom.firstChild;

        switch(Util.toClarkNotation(parentNode)) {
            case '{DAV:}unauthenticated' :
                return new jsDAV_Property_Principal(this.UNAUTHENTICATED);
            case '{DAV:}authenticated' :
                return new jsDAV_Property_Principal(this.AUTHENTICATED);
            case '{DAV:}href':
                return new jsDAV_Property_Principal(this.HREF, parentNode.textContent);
            case '{DAV:}all':
                return new jsDAV_Property_Principal(this.ALL);
            default:
                throw new Exc.jsDAV_Exception_BadRequest(
                    'Unexpected element ('+Util.toClarkNotation(parentNode)+'). Could not deserialize');
        }
    }
}).call(jsDAV_Property_Principal.prototype = new jsDAV_Property());

exports.jsDAV_Property_Principal = jsDAV_Property_Principal;
<commit_msg>Move principal property type constants out of prototype<commit_after>/*
 * @package jsDAV
 * @subpackage DAVACL
 * @copyright Copyright(c) 2011 Tri Tech Computers Ltd. <info AT tri-tech DOT com>
 * @author James Emerton <james AT tri-tech DOT com>
 * @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
 */

var Exc = require("./../../DAV/exceptions");
var Util = require("./../../DAV/util");

var jsDAV_Property = require("./../../DAV/property").jsDAV_Property;
var jsDAV_Property_Href = require("./../../DAV/property/href").jsDAV_Property_Href;

function jsDAV_Property_Principal(type, href) {
    this.type = type;
    if (type === jsDAV_Property_Principal.HREF && href === undefined) {
        throw new Exc.jsDAV_Exception('The href argument must be specified for the HREF principal type.');
    }
    this.href = href;
}

(function() {

    /**
     * To specify a not-logged-in user, use the UNAUTHENTICTED principal
     */
    jsDAV_Property_Principal.UNAUTHENTICATED = 1;

    /**
     * To specify any principal that is logged in, use AUTHENTICATED
     */
    jsDAV_Property_Principal.AUTHENTICATED = 2;

    /**
     * Specific principals can be specified with the HREF
     */
    jsDAV_Property_Principal.HREF = 3;

    /**
     * Everybody, basically
     */
    jsDAV_Property_Principal.ALL = 4;

    /**
     * Returns the principal type
     *
     * @return int
     */
    this.getType = function() {
        return this.type;
    }

    /**
     * Returns the principal uri.
     *
     * @return string
     */
    this.getHref = function() {
        return this.href;
    }

    this.serialize = function(handler, lmDom) {
        switch(this.type) {
            case jsDAV_Property_Principal.UNAUTHENTICATED:
                return lmDom+'<d:unauthenticated/>';

            case jsDAV_Property_Principal.AUTHENTICATED:
                return lmDom+'<d:authenticated/>';

            case jsDAV_Property_Principal.HREF:
                var href = new jsDAV_Property_Href(this.href, true);
                return href.serialize(handler, lmDom);
        }
    }

    /**
     * Deserializes a DOM element into a property object.
     *
     * @param DOMElement $dom
     * @return Sabre_DAV_Property_Principal
     */
    this.unserialize = function(dom) {
        var parentNode = dom.firstChild;

        switch(Util.toClarkNotation(parentNode)) {
            case '{DAV:}unauthenticated' :
                return new jsDAV_Property_Principal(jsDAV_Property_Principal.UNAUTHENTICATED);
            case '{DAV:}authenticated' :
                return new jsDAV_Property_Principal(jsDAV_Property_Principal.AUTHENTICATED);
            case '{DAV:}href':
                return new jsDAV_Property_Principal(jsDAV_Property_Principal.HREF, parentNode.textContent);
            case '{DAV:}all':
                return new jsDAV_Property_Principal(jsDAV_Property_Principal.ALL);
            default:
                throw new Exc.jsDAV_Exception_BadRequest(
                    'Unexpected element ('+Util.toClarkNotation(parentNode)+'). Could not deserialize');
        }
    }
}).call(jsDAV_Property_Principal.prototype = new jsDAV_Property());

exports.jsDAV_Property_Principal = jsDAV_Property_Principal;
<|endoftext|>