<commit_before>'use strict';

function WorldManager() {
    this.__init__();
}

WorldManager.prototype = {
    previous_world : null,
    current_world  : null,

    current_player_menu: null,

    // Pre-defined worlds.
    world_login    : null,
    world_home     : null,
    world_settings : null,

    world_global   : null,

    world_admin    : null,

    __init__: function() {
        this.world_login = new LoginWorld();
        this.world_home = new HomeWorld();
        this.world_settings = new SettingsWorld();
        this.world_admin = new AdminWorld();
    },

    //this.world_home.add_css_scene();

    update_current_world: function(delta) {

        // Temp just for fun, rotate the lights in a circle.
        this.current_world.light_delta += delta;
        this.current_world.light_percentage = this.current_world.light_delta / this.current_world.light_delta_cap;
        this.current_world.light_0.position.set(cos(this.current_world.light_percentage) * 1000, 100, sin(this.current_world.light_percentage) * 1000);
        this.current_world.light_1.position.set(cos(this.current_world.light_percentage + TWO_PIE / 4) * 1000, 100, sin(this.current_world.light_percentage + TWO_PIE / 4) * 1000);
        this.current_world.light_2.position.set(cos(this.current_world.light_percentage + (TWO_PIE / 4) * 2) * 1000, 100, sin(this.current_world.light_percentage + (TWO_PIE / 4) * 2) * 1000);
        this.current_world.light_3.position.set(cos(this.current_world.light_percentage + (TWO_PIE / 4) * 3) * 1000, 100, sin(this.current_world.light_percentage + (TWO_PIE / 4) * 3) * 1000);

        if (GUI_PAUSED_MENU.is_visible()) {
            return;
        }

        // TODO : Double check on what order these should update.

        if (MANAGER_WORLD.current_player_menu.is_visible()) {
            MANAGER_WORLD.current_player_menu.update(delta);
        }

        for (var a = 0; a < this.current_world.root_attachables.length; a++) {
            if (this.current_world.root_attachables[a].has_animation && this.root_attachables[a].requires_animation_update) {
                this.current_world.root_attachables[a].update(delta);
            }
            if (this.current_world.root_attachables[a].hasOwnProperty('update_all_child_animations_recursively')) {
                this.current_world.root_attachables[a].update_all_child_animations_recursively(delta);
            } else {
                l('Investigate this?');
            }
        }

        if (!this.current_world.floating_cursor._currently_engaged) {
            this.current_world.update_interactive_objects();
        }

        this.current_world.floating_cursor.update();

        //this.current_world.floating_cursor.update();
    },

    set_current_world: function(world) {
        if (this.current_world !== null) {
            // Before exiting the world make sure to remove the camera reference.
            this.current_world.remove_from_scene(CURRENT_PLAYER.fps_controls.yaw);
            this.current_world.exit_world();

            this.previous_world = this.current_world;
        }
        this.current_world = world;
        this.current_floating_cursor = this.current_world.floating_cursor;
        this.current_player_menu = this.current_world.player_menu;

        // Before adding the world make sure to add the camera reference.
        this.current_world.add_to_scene(CURRENT_PLAYER.fps_controls.yaw);
        this.current_world.enter_world();
    },

    key_down_event: function(event) {
        this.current_world.key_down_event_for_interactive_objects(event);
    },

    add_to_all_scenes: function(object) {
        this.world_login.add_to_scene(object);
        this.world_home.add_to_scene(object);
        this.world_settings.add_to_scene(object);

        // TODO : Make sure dynamic worlds are dealt with.
    },

    create_world: function(world) {
        world.light_delta = 0;
        world.light_delta_cap = 10;
        world.light_radius = 1000;

        world.player_menu.create();
        world.player_menu.set_to_invisible();

        world.floating_cursor.create();

        var skybox_geometry = new THREE.BoxGeometry(20000, 20000, 20000);
        var skybox_cube = new THREE.Mesh(skybox_geometry, MANAGER_LOADING.sky_box_material);
        skybox_cube.position.set(0, 0, 0);
        world.add_to_scene(skybox_cube);

        // Default hex grid ground.
        var grid = new vg.HexGrid({cellSize: 100});
        grid.generate({size: 10});
        var board = new vg.Board(grid);
        board.generateTilemap({cellSize: 100, tileScale: 0.99});
        world.add_to_scene(board.group);

        // Default lights.
        world.light_0 = new THREE.PointLight(0xccffcc, .4, 0);
        world.light_0.position.set(5, 100, 5);
        world.add_to_scene(world.light_0);

        world.light_1 = new THREE.PointLight(0xff8579, .4, 0);
        world.light_1.position.set(1000, 100, 0);
        world.add_to_scene(world.light_1);

        world.light_2 = new THREE.PointLight(0xb1ff90, .4, 0);
        world.light_2.position.set(0, 100, 1000);
        world.add_to_scene(world.light_2);

        world.light_3 = new THREE.PointLight(0x84b5ff, .4, 0);
        world.light_3.position.set(500, 100, 500);
        world.add_to_scene(world.light_3);
        /////////////////

        world.light = new THREE.AmbientLight(0xffffff, .25); // soft white light
        world.add_to_scene(world.light);

        // Now finally create the actual world.
        world.create();
    }

};

<commit_msg>schedule view abstraction 09<commit_after>'use strict';

function WorldManager() {
    this.__init__();
}

WorldManager.prototype = {
    previous_world : null,
    current_world  : null,

    current_player_menu: null,

    // Pre-defined worlds.
    world_login    : null,
    world_home     : null,
    world_settings : null,

    world_global   : null,

    world_admin    : null,

    __init__: function() {
        this.world_login = new LoginWorld();
        this.world_home = new HomeWorld();
        this.world_settings = new SettingsWorld();
        this.world_admin = new AdminWorld();
    },

    //this.world_home.add_css_scene();

    update_current_world: function(delta) {

        // Temp just for fun, rotate the lights in a circle.
        this.current_world.light_delta += delta;
        this.current_world.light_percentage = this.current_world.light_delta / this.current_world.light_delta_cap;
        this.current_world.light_0.position.set(cos(this.current_world.light_percentage) * 1000, 100, sin(this.current_world.light_percentage) * 1000);
        this.current_world.light_1.position.set(cos(this.current_world.light_percentage + TWO_PIE / 4) * 1000, 100, sin(this.current_world.light_percentage + TWO_PIE / 4) * 1000);
        this.current_world.light_2.position.set(cos(this.current_world.light_percentage + (TWO_PIE / 4) * 2) * 1000, 100, sin(this.current_world.light_percentage + (TWO_PIE / 4) * 2) * 1000);
        this.current_world.light_3.position.set(cos(this.current_world.light_percentage + (TWO_PIE / 4) * 3) * 1000, 100, sin(this.current_world.light_percentage + (TWO_PIE / 4) * 3) * 1000);

        if (GUI_PAUSED_MENU.is_visible()) {
            return;
        }

        // TODO : Double check on what order these should update.

        if (MANAGER_WORLD.current_player_menu.is_visible()) {
            MANAGER_WORLD.current_player_menu.update(delta);
        }

        for (var a = 0; a < this.current_world.root_attachables.length; a++) {
            if (this.current_world.root_attachables[a].has_animation && this.root_attachables[a].requires_animation_update) {
                this.current_world.root_attachables[a].update(delta);
            }
            if (this.current_world.root_attachables[a].hasOwnProperty('update_all_child_animations_recursively')) {
                this.current_world.root_attachables[a].update_all_child_animations_recursively(delta);
            } else {
                l('Investigate this?');
            }
        }

        if (!this.current_world.floating_cursor._currently_engaged) {
            this.current_world.update_interactive_objects();
        }

        this.current_world.floating_cursor.update();

        //this.current_world.floating_cursor.update();
    },

    set_current_world: function(world) {
        if (this.current_world !== null) {
            // Before exiting the world make sure to remove the camera reference.
            this.current_world.remove_from_scene(CURRENT_PLAYER.fps_controls.yaw);
            this.current_world.exit_world();

            this.previous_world = this.current_world;
        }
        this.current_world = world;
        this.current_floating_cursor = this.current_world.floating_cursor;
        this.current_player_menu = this.current_world.player_menu;

        // Before adding the world make sure to add the camera reference.
        this.current_world.add_to_scene(CURRENT_PLAYER.fps_controls.yaw);
        this.current_world.enter_world();
    },

    key_down_event: function(event) {
        this.current_world.key_down_event_for_interactive_objects(event);
    },

    add_to_all_scenes: function(object) {
        this.world_login.add_to_scene(object);
        this.world_home.add_to_scene(object);
        this.world_settings.add_to_scene(object);

        // TODO : Make sure dynamic worlds are dealt with.
    },

    create_world: function(world) {
        world.light_delta = 0;
        world.light_delta_cap = 10;
        world.light_radius = 1000;

        world.player_menu.create();
        world.player_menu.set_to_invisible();

        world.floating_cursor.create();

        var skybox_geometry = new THREE.BoxGeometry(22500, 22500, 22500);
        var skybox_cube = new THREE.Mesh(skybox_geometry, MANAGER_LOADING.sky_box_material);
        skybox_cube.position.set(0, 0, 0);
        world.add_to_scene(skybox_cube);

        // Default hex grid ground.
        var grid = new vg.HexGrid({cellSize: 100});
        grid.generate({size: 10});
        var board = new vg.Board(grid);
        board.generateTilemap({cellSize: 100, tileScale: 0.99});
        world.add_to_scene(board.group);

        // Default lights.
        world.light_0 = new THREE.PointLight(0xccffcc, .4, 0);
        world.light_0.position.set(5, 100, 5);
        world.add_to_scene(world.light_0);

        world.light_1 = new THREE.PointLight(0xff8579, .4, 0);
        world.light_1.position.set(1000, 100, 0);
        world.add_to_scene(world.light_1);

        world.light_2 = new THREE.PointLight(0xb1ff90, .4, 0);
        world.light_2.position.set(0, 100, 1000);
        world.add_to_scene(world.light_2);

        world.light_3 = new THREE.PointLight(0x84b5ff, .4, 0);
        world.light_3.position.set(500, 100, 500);
        world.add_to_scene(world.light_3);
        /////////////////

        world.light = new THREE.AmbientLight(0xffffff, .25); // soft white light
        world.add_to_scene(world.light);

        // Now finally create the actual world.
        world.create();
    }

};

<|endoftext|>


<commit_before>const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect;

var t9 = require('../src/t9');

describe.only('T9', () => {
  it('should not replace anything if no power words present', () => {
    const path = 'aaa';
    expect(t9(path)).to.equal(path);
  });

  it('should find power words', () => {
    const a = t9.reverseT9('ei!');
    console.log(t9.reversePowerWords);
    const path = 'daaakamakmmmaamaambbb';
    expect(t9(path)).to.equal('digitalismmmialialbbb')
  })
});
<commit_msg>.only<commit_after>const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect;

var t9 = require('../src/t9');

describe('T9', () => {
  it('should not replace anything if no power words present', () => {
    const path = 'aaa';
    expect(t9(path)).to.equal(path);
  });

  it('should find power words', () => {
    const a = t9.reverseT9('ei!');
    console.log(t9.reversePowerWords);
    const path = 'daaakamakmmmaamaambbb';
    expect(t9(path)).to.equal('digitalismmmialialbbb')
  })
});
<|endoftext|>


<commit_before>const express = require('express');
const router = express.Router();

const getChartImage = require('../utils/getChartImage');
const getMinimalUrl = require('../utils/getMinimalUrl');
const shouldScreencapUrl = require('../utils/shouldScreencapUrl');

router.get('/', async function(req, res, next) {
  if (!req.query.url) {
    res.status(400).send({
      message: 'Please pass a url on the query string',
    });
  } else if (!shouldScreencapUrl(req.query.url)) {
    // res.status(400).send({
    //   message: `"url" param of ${req.query.url} is not valid`,
    // });
    res.redirect('https://npmcharts.com/images/og-image-3.png');
  } else {
    try {
      const imageBuffer = await getChartImage(getMinimalUrl(req.query.url));
      res.contentType('image/png');
      res.send(imageBuffer);
    } catch (e) {
      res.status(500).send(e);
    }
  }
});

module.exports = router;
<commit_msg>log chart image errors better<commit_after>const express = require('express');
const router = express.Router();

const getChartImage = require('../utils/getChartImage');
const getMinimalUrl = require('../utils/getMinimalUrl');
const shouldScreencapUrl = require('../utils/shouldScreencapUrl');

router.get('/', async function(req, res, next) {
  if (!req.query.url) {
    res.status(400).send({
      message: 'Please pass a url on the query string',
    });
  } else if (!shouldScreencapUrl(req.query.url)) {
    // res.status(400).send({
    //   message: `"url" param of ${req.query.url} is not valid`,
    // });
    res.redirect('https://npmcharts.com/images/og-image-3.png');
  } else {
    try {
      const imageBuffer = await getChartImage(getMinimalUrl(req.query.url));
      res.contentType('image/png');
      res.send(imageBuffer);
    } catch (e) {
      console.error(e);
      res.status(500).send({ error: e.toString() });
    }
  }
});

module.exports = router;
<|endoftext|>


<commit_before>// This is going to be part of add-on SDK, but the original (with modifications
// to properly decode stdout) is used as of now.
// https://github.com/mozilla/addon-sdk/tree/master/lib/sdk/system/child_process
Components.utils.import("resource://tb-goa/subprocess.js");

window.addEventListener("load", function(e) {
    startup();
}, false);

window.setInterval(
    function() {
        startup();
    }, 60000); //update date every minute

function startup() {
    var content_node = document.getElementById("goa-content");

    var accounts_xml = '';
    subprocess.call({
        command: '/usr/bin/dbus-send',
        arguments: [
            "--dest=org.gnome.OnlineAccounts", "--print-reply=literal",
            "/org/gnome/OnlineAccounts/Accounts", "org.freedesktop.DBus.Introspectable.Introspect"
        ],
        done: function(result) {
            accounts_xml = result.stdout;
        },
        mergeStderr: false
    }).wait();

    var parser = new DOMParser();
    var accounts_dom = parser.parseFromString(accounts_xml, "text/xml");
    var account_nodes = accounts_dom.documentElement.childNodes;

    var accounts = [];
    for(var i = 0; i < account_nodes.length; i++) {
        if (account_nodes[i].nodeType == 1) {
            accounts.push(account_nodes[i].attributes.getNamedItem("name").nodeValue);
        }
    }

    for(var i = 0; i < accounts.length; i++) {
        content_node.appendChild(
            document.createTextNode(accounts[i] + '\n')
        );
    }

    var output = '';
    subprocess.call({
        command: '/usr/bin/dbus-send',
        arguments: [
            "--dest=org.gnome.OnlineAccounts", "--print-reply",
            "/org/gnome/OnlineAccounts/Accounts/account_1431601757_1", "org.gnome.OnlineAccounts.OAuth2Based.GetAccessToken"
        ],
        done: function(result) {
            output = result.stdout;
        },
        mergeStderr: false
    }).wait();

    content_node.appendChild(
        document.createTextNode(output)
    );
}
<commit_msg>Discover Calendar account and get its token.<commit_after>// This is going to be part of add-on SDK, but the original (with modifications
// to properly decode stdout) is used as of now.
// https://github.com/mozilla/addon-sdk/tree/master/lib/sdk/system/child_process
Components.utils.import("resource://tb-goa/subprocess.js");

window.addEventListener("load", function(e) {
    startup();
}, false);

window.setInterval(
    function() {
        startup();
    }, 60000); //update date every minute

function startup() {
    var content_node = document.getElementById("goa-content");

    // Enumerate accounts.
    var accounts_xml = '';
    subprocess.call({
        command: '/usr/bin/dbus-send',
        arguments: [
            "--dest=org.gnome.OnlineAccounts", "--print-reply=literal",
            "/org/gnome/OnlineAccounts/Accounts", "org.freedesktop.DBus.Introspectable.Introspect"
        ],
        done: function(result) {
            accounts_xml = result.stdout;
        },
        mergeStderr: false
    }).wait();

    var parser = new DOMParser();

    var accounts_dom = parser.parseFromString(accounts_xml, "text/xml");
    var account_nodes = accounts_dom.documentElement.childNodes;

    var accounts = [];
    for(var i = 0; i < account_nodes.length; i++) {
        if (account_nodes[i].nodeType == 1) {
            accounts.push(account_nodes[i].attributes.getNamedItem("name").nodeValue);
        }
    }

    // Enumerate properties of each account.
    var calendar_accounts = {};
    for(var i = 0; i < accounts.length; i++) {
        var account_xml = '';
        subprocess.call({
            command: '/usr/bin/dbus-send',
            arguments: [
                "--dest=org.gnome.OnlineAccounts", "--print-reply=literal",
                "/org/gnome/OnlineAccounts/Accounts/" + accounts[i], "org.freedesktop.DBus.Introspectable.Introspect"
            ],
            done: function(result) {
                account_xml = result.stdout;
            },
            mergeStderr: false
        }).wait();

        var account_dom = parser.parseFromString(account_xml, "text/xml");
        var interface_nodes = account_dom.getElementsByTagName("interface");

        for(var n = 0; n < interface_nodes.length; n++) {
            var name = interface_nodes[n].getAttribute("name");
            if (name == "org.gnome.OnlineAccounts.Calendar") {
                calendar_accounts[accounts[i]] = account_dom;
                break;
            }
        }
    }

    for(var ca in calendar_accounts) {
       var access_token_string = '';
       subprocess.call({
           command: '/usr/bin/dbus-send',
           arguments: [
               "--dest=org.gnome.OnlineAccounts", "--print-reply",
               "/org/gnome/OnlineAccounts/Accounts/" + ca, "org.gnome.OnlineAccounts.OAuth2Based.GetAccessToken"
           ],
           done: function(result) {
               access_token_string = result.stdout;
           },
           mergeStderr: false,
       }).wait();

       var access_token_lines = access_token_string.split('\n');
       var access_token = access_token_lines[1].trim().split('"')[1];
       var access_token_expires_in = access_token_lines[2].trim().split(' ')[1];
       content_node.appendChild(
           document.createTextNode(access_token + '\n')
       );
       content_node.appendChild(
           document.createTextNode(access_token_expires_in + '\n')
       );
    }
}
<|endoftext|>


<commit_before>define(["backbone", "underscore", "gettext", "js/models/validation_helpers", "js/utils/date_utils"],
    function(Backbone, _, gettext, ValidationHelpers, DateUtils) {

var CourseDetails = Backbone.Model.extend({
    defaults: {
        org : '',
        course_id: '',
        run: '',
        language: '',
        start_date: null,	// maps to 'start'
        end_date: null,		// maps to 'end'
        enrollment_start: null,
        enrollment_end: null,
        syllabus: null,
        title: "",
        subtitle: "",
        duration: "",
        description: "",
        short_description: "",
        overview: "",
        intro_video: null,
        effort: null,	// an int or null,
        license: null,
        course_image_name: '', // the filename
        course_image_asset_path: '', // the full URL (/c4x/org/course/num/asset/filename)
        banner_image_name: '',
        banner_image_asset_path: '',
        video_thumbnail_image_name: '',
        video_thumbnail_image_asset_path: '',
        pre_requisite_courses: [],
        entrance_exam_enabled : '',
        entrance_exam_minimum_score_pct: '50',
        learning_info: [],
        instructor_info: {}
    },

    validate: function(newattrs) {
        // Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
        // A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
        var errors = {};
        newattrs = DateUtils.convertDateStringsToObjects(
            newattrs, ["start_date", "end_date", "enrollment_start", "enrollment_end"]
        );

        if (newattrs.title.length > 50) {
            errors.title = gettext("The title field must be limited to 50 characters.");
        }

        if (newattrs.subtitle.length > 150) {
            errors.subtitle = gettext("The subtitle field must be limited to 150 characters.");
        }

        if (newattrs.duration.length > 50) {
            errors.duration = gettext("The duration field must be limited to 50 characters.");
        }

        if (newattrs.short_description.length > 150) {
            errors.short_description = gettext("The short description field must be limited to 150 characters.");
        }

        if (newattrs.description.length > 1000) {
            errors.description = gettext("The description field must be limited to 1000 characters.");
        }

        if (newattrs.start_date === null) {
            errors.start_date = gettext("The course must have an assigned start date.");
        }

        if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
            errors.end_date = gettext("The course end date must be later than the course start date.");
        }
        if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
            errors.enrollment_start = gettext("The course start date must be later than the enrollment start date.");
        }
        if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
            errors.enrollment_end = gettext("The enrollment start date cannot be after the enrollment end date.");
        }
        if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
            errors.enrollment_end = gettext("The enrollment end date cannot be after the course end date.");
        }
        if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
            if (this._videokey_illegal_chars.exec(newattrs.intro_video)) {
                errors.intro_video = gettext("Key should only contain letters, numbers, _, or -");
            }
            // TODO check if key points to a real video using google's youtube api
        }
        if(_.has(newattrs, 'entrance_exam_minimum_score_pct')){
            var range = {
                min: 1,
                max: 100
            };
            if(!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)){
                errors.entrance_exam_minimum_score_pct = interpolate(gettext("Please enter an integer between %(min)s and %(max)s."), range, true);
            }
        }
        if (!_.isEmpty(errors)) return errors;
        // NOTE don't return empty errors as that will be interpreted as an error state
    },

    _videokey_illegal_chars : /[^a-zA-Z0-9_-]/g,

    set_videosource: function(newsource) {
        // newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string
        // returns the videosource for the preview which iss the key whose speed is closest to 1
        if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({'intro_video': null}, {validate: true});
        // TODO remove all whitespace w/in string
        else {
            if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true});
        }

        return this.videosourceSample();
    },

    videosourceSample : function() {
        if (this.has('intro_video')) return "//www.youtube.com/embed/" + this.get('intro_video');
        else return "";
    },

    // Whether or not the course pacing can be toggled. If the course
    // has already started, returns false; otherwise, returns true.
    canTogglePace: function () {
        return new Date() <= new Date(this.get('start_date'));
    }
});

return CourseDetails;

}); // end define()
<commit_msg>Remove course details field character limits<commit_after>define(["backbone", "underscore", "gettext", "js/models/validation_helpers", "js/utils/date_utils"],
    function(Backbone, _, gettext, ValidationHelpers, DateUtils) {

var CourseDetails = Backbone.Model.extend({
    defaults: {
        org : '',
        course_id: '',
        run: '',
        language: '',
        start_date: null,	// maps to 'start'
        end_date: null,		// maps to 'end'
        enrollment_start: null,
        enrollment_end: null,
        syllabus: null,
        title: "",
        subtitle: "",
        duration: "",
        description: "",
        short_description: "",
        overview: "",
        intro_video: null,
        effort: null,	// an int or null,
        license: null,
        course_image_name: '', // the filename
        course_image_asset_path: '', // the full URL (/c4x/org/course/num/asset/filename)
        banner_image_name: '',
        banner_image_asset_path: '',
        video_thumbnail_image_name: '',
        video_thumbnail_image_asset_path: '',
        pre_requisite_courses: [],
        entrance_exam_enabled : '',
        entrance_exam_minimum_score_pct: '50',
        learning_info: [],
        instructor_info: {}
    },

    validate: function(newattrs) {
        // Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
        // A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
        var errors = {};
        newattrs = DateUtils.convertDateStringsToObjects(
            newattrs, ["start_date", "end_date", "enrollment_start", "enrollment_end"]
        );

        if (newattrs.start_date === null) {
            errors.start_date = gettext("The course must have an assigned start date.");
        }

        if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
            errors.end_date = gettext("The course end date must be later than the course start date.");
        }
        if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
            errors.enrollment_start = gettext("The course start date must be later than the enrollment start date.");
        }
        if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
            errors.enrollment_end = gettext("The enrollment start date cannot be after the enrollment end date.");
        }
        if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
            errors.enrollment_end = gettext("The enrollment end date cannot be after the course end date.");
        }
        if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
            if (this._videokey_illegal_chars.exec(newattrs.intro_video)) {
                errors.intro_video = gettext("Key should only contain letters, numbers, _, or -");
            }
            // TODO check if key points to a real video using google's youtube api
        }
        if(_.has(newattrs, 'entrance_exam_minimum_score_pct')){
            var range = {
                min: 1,
                max: 100
            };
            if(!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)){
                errors.entrance_exam_minimum_score_pct = interpolate(gettext("Please enter an integer between %(min)s and %(max)s."), range, true);
            }
        }
        if (!_.isEmpty(errors)) return errors;
        // NOTE don't return empty errors as that will be interpreted as an error state
    },

    _videokey_illegal_chars : /[^a-zA-Z0-9_-]/g,

    set_videosource: function(newsource) {
        // newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string
        // returns the videosource for the preview which iss the key whose speed is closest to 1
        if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({'intro_video': null}, {validate: true});
        // TODO remove all whitespace w/in string
        else {
            if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true});
        }

        return this.videosourceSample();
    },

    videosourceSample : function() {
        if (this.has('intro_video')) return "//www.youtube.com/embed/" + this.get('intro_video');
        else return "";
    },

    // Whether or not the course pacing can be toggled. If the course
    // has already started, returns false; otherwise, returns true.
    canTogglePace: function () {
        return new Date() <= new Date(this.get('start_date'));
    }
});

return CourseDetails;

}); // end define()
<|endoftext|>


<commit_before>/*global describe: false, it: false, require: false */
"use strict";
var lens = require('../../js/lenses/lens');
var _ = require('../../js/underscore_ext');
var assert = require('assert');
describe('lenses/lens', function () {
    describe('#lens', function () {
        it('should get', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo));

            assert.deepEqual(lens.view(fooLens, {foo: 5, bar: 7}), 5);
            assert.deepEqual(lens.view(fooLens, {foo: ['hello'], bar: 7}), ['hello']);
        });
        it('should set', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo));

            assert.deepEqual(lens.set(fooLens, {foo: 5, bar: 7}, ['hello']), {foo: ['hello'], bar: 7});
            assert.deepEqual(lens.set(fooLens, {foo: ['hello'], bar: 7}, 12), {foo: 12, bar: 7});
        });
        it('should compose with other lenses', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                thirdLens = lens.lens(x => x[2], (x, third) => _.assoc(x, 2, third)),
                thirdFooLens = _.compose(thirdLens, fooLens);

            assert.deepEqual(lens.view(thirdFooLens, [{foo: 12}, {foo: 2}, {foo: 'bingo'}]), 'bingo');
            assert.deepEqual(lens.set(thirdFooLens, [{foo: 12}, {foo: 2}, {foo: 'bingo'}], 'hork'), [{foo: 12}, {foo: 2}, {foo: 'hork'}]);
        });
        it('should work with closed-over getter/setter', function() {
            var state = {some: "state"},
                mutLens = lens.lens(() => state, (x, s) => state = s);

            assert.deepEqual(lens.view(mutLens, {foo: 5, bar: 7}), {some: "state"});
            assert.deepEqual(lens.set(mutLens, {foo: 5, bar: 7}, {different: "state"}), {different: "state"});
            assert.deepEqual(state, {different: "state"});
        });
        function spy(msg, x) {
            /*global console: false */
            console.log(msg, x);
            return x;
        }
        // 'should only call setter once'
        it('should compose with closed-over getter/setter', function() {
            var state = {foo: "state"},
                mutLens = lens.lens(() => state, (x, s) => spy('setting', state = s)),
                fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                mutFooLens = inj => mutLens(fooLens(inj));

            assert.deepEqual(lens.view(mutFooLens), "state");
            assert.deepEqual(state, {foo: "state"});
            assert.deepEqual(lens.set(mutFooLens, undefined, "hork"), {foo: "hork"});
            assert.deepEqual(state, {foo: "hork"}); // XXX put in separate test?
        });
        it('should compose twice with closed-over getter/setter', function() {
            var state = [{foo: "one"}, {foo: "two"}, {foo: "three"}],
                mutLens = lens.lens(() => state, (x, s) => spy('setting', state = s)),
                fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                thirdLens = lens.lens(x => x[2], (x, third) => _.assoc(x, 2, third)),
                mutThirdFooLens = inj => mutLens(thirdLens(fooLens(inj)));

            assert.deepEqual(lens.view(mutThirdFooLens), "three");
            assert.deepEqual(state, [{foo: "one"}, {foo: "two"}, {foo: "three"}]);
            assert.deepEqual(lens.set(mutThirdFooLens, undefined, "hork"), [{foo: "one"}, {foo: "two"}, {foo: "hork"}]);
            assert.deepEqual(state, [{foo: "one"}, {foo: "two"}, {foo: "hork"}]);
        });
    });
});
<commit_msg>Drop debug logging.<commit_after>/*global describe: false, it: false, require: false */
"use strict";
var lens = require('../../js/lenses/lens');
var _ = require('../../js/underscore_ext');
var assert = require('assert');
describe('lenses/lens', function () {
    describe('#lens', function () {
        it('should get', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo));

            assert.deepEqual(lens.view(fooLens, {foo: 5, bar: 7}), 5);
            assert.deepEqual(lens.view(fooLens, {foo: ['hello'], bar: 7}), ['hello']);
        });
        it('should set', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo));

            assert.deepEqual(lens.set(fooLens, {foo: 5, bar: 7}, ['hello']), {foo: ['hello'], bar: 7});
            assert.deepEqual(lens.set(fooLens, {foo: ['hello'], bar: 7}, 12), {foo: 12, bar: 7});
        });
        it('should compose with other lenses', function() {
            var fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                thirdLens = lens.lens(x => x[2], (x, third) => _.assoc(x, 2, third)),
                thirdFooLens = _.compose(thirdLens, fooLens);

            assert.deepEqual(lens.view(thirdFooLens, [{foo: 12}, {foo: 2}, {foo: 'bingo'}]), 'bingo');
            assert.deepEqual(lens.set(thirdFooLens, [{foo: 12}, {foo: 2}, {foo: 'bingo'}], 'hork'), [{foo: 12}, {foo: 2}, {foo: 'hork'}]);
        });
        it('should work with closed-over getter/setter', function() {
            var state = {some: "state"},
                mutLens = lens.lens(() => state, (x, s) => state = s);

            assert.deepEqual(lens.view(mutLens, {foo: 5, bar: 7}), {some: "state"});
            assert.deepEqual(lens.set(mutLens, {foo: 5, bar: 7}, {different: "state"}), {different: "state"});
            assert.deepEqual(state, {different: "state"});
        });
        // 'should only call setter once'
        it('should compose with closed-over getter/setter', function() {
            var state = {foo: "state"},
                mutLens = lens.lens(() => state, (x, s) => state = s),
                fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                mutFooLens = inj => mutLens(fooLens(inj));

            assert.deepEqual(lens.view(mutFooLens), "state");
            assert.deepEqual(state, {foo: "state"});
            assert.deepEqual(lens.set(mutFooLens, undefined, "hork"), {foo: "hork"});
            assert.deepEqual(state, {foo: "hork"}); // XXX put in separate test?
        });
        it('should compose twice with closed-over getter/setter', function() {
            var state = [{foo: "one"}, {foo: "two"}, {foo: "three"}],
                mutLens = lens.lens(() => state, (x, s) => state = s),
                fooLens = lens.lens(x => x.foo, (x, foo) => _.assoc(x, 'foo', foo)),
                thirdLens = lens.lens(x => x[2], (x, third) => _.assoc(x, 2, third)),
                mutThirdFooLens = inj => mutLens(thirdLens(fooLens(inj)));

            assert.deepEqual(lens.view(mutThirdFooLens), "three");
            assert.deepEqual(state, [{foo: "one"}, {foo: "two"}, {foo: "three"}]);
            assert.deepEqual(lens.set(mutThirdFooLens, undefined, "hork"), [{foo: "one"}, {foo: "two"}, {foo: "hork"}]);
            assert.deepEqual(state, [{foo: "one"}, {foo: "two"}, {foo: "hork"}]);
        });
    });
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/components/karbon-sortable-list';

/**
 * A container for sortable items. Items within the list can be sorted via
 * dragging and dropping them into a new position. You can also identify
 * external drop targets for non-sorting actions.
 */

export default Ember.Component.extend({
  tagName: 'ul',
  classNames: ['karbon-sortable-list'],
  classNameBindings: ['containerClass'],

  layout,
  // is the nesting feature enabled or not
  canNest: false,
  nestTolerance: 60,

  // The DOM element being dragged
  _draggedEl: null,
  // The initial screenX position at the beginning of a drag
  _screenX: null,

  // We enable/disable nesting during certain operations, regardless
  // of the canNest user setting
  _nestingEnabled: true,

  // When dragging parents and children, keep the data here
  _dragGroup: null,

  _getChildren: function(node) {
    let children = [];
    const data = this.get('data');
    const index = Ember.$(node).index();

    console.log('getChildren for: ', data.objectAt(index).get('title'),
                ' isChild: ', data.objectAt(index).get('isChild'));

    // we must not be a child
    if (data.objectAt(index).get('isChild')) {
      return [];
    }

    // must have at least one item below us
    if (index < (data.get('length') - 1)) {

      let nextPos = index + 1;
      let nextNode = Ember.$(node).next();
      let nextData = data.objectAt(nextPos);

      while (nextData.get('isChild')) {
        children.push(nextNode);
        nextNode = Ember.$(nextNode).next();
        nextPos++;
        if (nextPos >= data.get('length')) {
          break;
        }
        nextData = data.objectAt(nextPos);
      }
    }

    console.log('hasChildren: ', children.length);

    return children;
  },

  nestingAllowed: Ember.computed('canNest', '_nestingEnabled', function() {
    return this.get('canNest') && this.get('_nestingEnabled');
  }),

  didInsertElement() {
    this.$().on('dragstart.karbonsortable', (event) => {
      event.dataTransfer.effectAllowed = 'move';
      event.dataTransfer.dropEffect = 'move';

      this.set('_draggedEl', event.target);
      if (this.get('nestingAllowed')) {
        let children = this._getChildren(event.target);
        if (children.length > 0) {
          // We are dragging a group, so normal nesting rules do not apply
          this.set('_nestingEnabled', false);

          Ember.$(event.target).removeClass('droppable');

          children.forEach( (child) => {
            let childEl = Ember.$(child);
            childEl.addClass('dragging');
            childEl.removeClass('droppable');
          });

          event.dataTransfer.setDragImage(document.getElementById('dragGroupImage'), 25, 25);

          this.set('_dragGroup', children);

        } else {
          // alway reset the screenX when starting a drag, it will be used as the
          // basis for detecting deltaX
          this.set('_screenX', null);
        }
      }

      event.target.classList.add('dragging');
    });

    this.$().on('dragend.karbonsortable', (event) => {
      if (event.dataTransfer.dropEffect) {
          event.target.classList.add('dropping');
          event.target.classList.add('droppable');
          Ember.run.later( () => {
              event.target.classList.remove('dragging');
              event.target.classList.remove('dropping');
          }, 1000);
      }

      const children = this.get('_dragGroup');
      Ember.run.later( () => {
        if (children) {
          children.forEach( (child) => {
            let childEl = Ember.$(child);
            childEl.removeClass('dragging');
            childEl.addClass('droppable');
          });
        }
      }, 200);

      this.set('_nestingEnabled', true);
    });

    this.$().on('dragenter.karbonsortable', (event) => {
      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable');

      if (droppable.length === 1) {
        droppable.addClass('droppable--enter');
      }
    });

    this.$().on('dragover.karbonsortable', (event) => {
      // prevent default to allow drop
      event.preventDefault();

      if (this.get('nestingAllowed')) {
        const item = Ember.$(event.target);
        const droppable = item.closest('.droppable');
        const dragged = this.get('_draggedEl');

        let isSame = false;

        if (dragged && droppable.length && (dragged.id === droppable[0].id)) {
          isSame = true;
        }

        if (droppable.length === 1 && isSame) {
          const index = Ember.$(droppable).index();
          const isChild = this.get('data').objectAt(index).get('isChild');

          const screenX = this.get('_screenX');
          const newScreenX = event.originalEvent.screenX;

          if (!screenX) {
            this.set('_screenX', newScreenX);
          } else {
            const deltaX = newScreenX - screenX;
            const nestTolerance = this.get('nestTolerance');

            if (deltaX < (-1 * nestTolerance)) {
              // outdent
              droppable.removeClass('nesting');
              if (isChild) {
                droppable.removeClass('nested');
              }
            } else if (deltaX > nestTolerance) {
              // indent
              droppable.addClass('nesting');
            }
          }
        }
      }

    });

    this.$().on('dragleave.karbonsortable', (event) => {
      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable--enter');

      if (droppable.length === 1) {
        droppable.removeClass('droppable--enter');
        if (this.get('nestingAllowed')) {
          const index = Ember.$(droppable).index();
          const isChild = this.get('data').objectAt(index).get('isChild');

          droppable.removeClass('nesting');
          if (isChild) {
            droppable.addClass('nested');
          }
        }
      }
    });

    this.$().on('drop.karbonsortable', (event) => {
      event.preventDefault();

      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable--enter');
      let isChild = false;
      let isSame = false;

      if (droppable.length === 1) {
        let newIndex = Ember.$(droppable).index();

        const dragged = this.get('_draggedEl');

        // need a better equality test
        if (dragged.id === droppable[0].id) {
          isSame = true;
        }

        // nesting will not be allowed if the drop is for a parent
        if (this.get('nestingAllowed')) {
          const screenX = this.get('_screenX');
          const newScreenX = event.originalEvent.screenX;
          const deltaX = newScreenX - screenX;
          const nestTolerance = this.get('nestTolerance');

          if (deltaX > nestTolerance || droppable.hasClass('nesting')) {
            // indent
            dragged.classList.add('nested');
            isChild = true;
          } else if (deltaX < (-1 * nestTolerance)) {
            // outdent
            dragged.classList.remove('nested');
          }

          if (!isSame && this.get('data').objectAt(newIndex).get('isChild')) {
            droppable.addClass('nested');
          }

          droppable.removeClass('nesting');
        }

        const oldIndex = Ember.$(dragged).index();
        const data = this.get('data');
        const dataItem = data.objectAt(oldIndex);

        droppable.removeClass('droppable--enter');

        const children = this.get('_dragGroup');

        // Move the data, have to keep the list in sync
        if (!isSame) {
          data.removeAt(oldIndex);
          data.insertAt(newIndex, dataItem);

          if (children) {
            // dragging down
            if (newIndex > oldIndex) {
              for (let i = 1; i <= children.length; i++) {
                let child = data.objectAt(oldIndex);

                data.removeAt(oldIndex);
                data.insertAt(newIndex, child);
              }
            } else {
              // dragging up
              for (let i = 1; i <= children.length; i++) {
                let child = data.objectAt(oldIndex + i);

                data.removeAt(oldIndex + i);
                data.insertAt(newIndex + i, child);
              }
            }

            Ember.run.later( () => {
              if (children) {
                children.forEach( (child) => {
                  let childEl = Ember.$(child);
                  childEl.removeClass('dragging');
                  childEl.addClass('droppable');
                });
              }
            }, 200);

          }
        }

        this.set('_dragGroup', null);

        dataItem.set('isChild', isChild);

        this.get('onOrderChanged')(dataItem, oldIndex, newIndex, isChild);
      }
    });
  },

  willDestroyElement() {
    this.$().off('dragstart.karbonsortable');
    this.$().off('dragend.karbonsortable');
    this.$().off('dragenter.karbonsortable');
    this.$().off('dragover.karbonsortable');
    this.$().off('dragleave.karbonsortable');
    this.$().off('drop.karbonsortable');
  }
});
<commit_msg>Remove logging.<commit_after>import Ember from 'ember';
import layout from '../templates/components/karbon-sortable-list';

/**
 * A container for sortable items. Items within the list can be sorted via
 * dragging and dropping them into a new position. You can also identify
 * external drop targets for non-sorting actions.
 */

export default Ember.Component.extend({
  tagName: 'ul',
  classNames: ['karbon-sortable-list'],
  classNameBindings: ['containerClass'],

  layout,
  // is the nesting feature enabled or not
  canNest: false,
  nestTolerance: 60,

  // The DOM element being dragged
  _draggedEl: null,
  // The initial screenX position at the beginning of a drag
  _screenX: null,

  // We enable/disable nesting during certain operations, regardless
  // of the canNest user setting
  _nestingEnabled: true,

  // When dragging parents and children, keep the data here
  _dragGroup: null,

  _getChildren: function(node) {
    let children = [];
    const data = this.get('data');
    const index = Ember.$(node).index();

    // we must not be a child
    if (data.objectAt(index).get('isChild')) {
      return [];
    }

    // must have at least one item below us
    if (index < (data.get('length') - 1)) {

      let nextPos = index + 1;
      let nextNode = Ember.$(node).next();
      let nextData = data.objectAt(nextPos);

      while (nextData.get('isChild')) {
        children.push(nextNode);
        nextNode = Ember.$(nextNode).next();
        nextPos++;
        if (nextPos >= data.get('length')) {
          break;
        }
        nextData = data.objectAt(nextPos);
      }
    }

    return children;
  },

  nestingAllowed: Ember.computed('canNest', '_nestingEnabled', function() {
    return this.get('canNest') && this.get('_nestingEnabled');
  }),

  didInsertElement() {
    this.$().on('dragstart.karbonsortable', (event) => {
      event.dataTransfer.effectAllowed = 'move';
      event.dataTransfer.dropEffect = 'move';

      this.set('_draggedEl', event.target);
      if (this.get('nestingAllowed')) {
        let children = this._getChildren(event.target);
        if (children.length > 0) {
          // We are dragging a group, so normal nesting rules do not apply
          this.set('_nestingEnabled', false);

          Ember.$(event.target).removeClass('droppable');

          children.forEach( (child) => {
            let childEl = Ember.$(child);
            childEl.addClass('dragging');
            childEl.removeClass('droppable');
          });

          event.dataTransfer.setDragImage(document.getElementById('dragGroupImage'), 25, 25);

          this.set('_dragGroup', children);

        } else {
          // alway reset the screenX when starting a drag, it will be used as the
          // basis for detecting deltaX
          this.set('_screenX', null);
        }
      }

      event.target.classList.add('dragging');
    });

    this.$().on('dragend.karbonsortable', (event) => {
      if (event.dataTransfer.dropEffect) {
          event.target.classList.add('dropping');
          event.target.classList.add('droppable');
          Ember.run.later( () => {
              event.target.classList.remove('dragging');
              event.target.classList.remove('dropping');
          }, 1000);
      }

      const children = this.get('_dragGroup');
      Ember.run.later( () => {
        if (children) {
          children.forEach( (child) => {
            let childEl = Ember.$(child);
            childEl.removeClass('dragging');
            childEl.addClass('droppable');
          });
        }
      }, 200);

      this.set('_nestingEnabled', true);
    });

    this.$().on('dragenter.karbonsortable', (event) => {
      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable');

      if (droppable.length === 1) {
        droppable.addClass('droppable--enter');
      }
    });

    this.$().on('dragover.karbonsortable', (event) => {
      // prevent default to allow drop
      event.preventDefault();

      if (this.get('nestingAllowed')) {
        const item = Ember.$(event.target);
        const droppable = item.closest('.droppable');
        const dragged = this.get('_draggedEl');

        let isSame = false;

        if (dragged && droppable.length && (dragged.id === droppable[0].id)) {
          isSame = true;
        }

        if (droppable.length === 1 && isSame) {
          const index = Ember.$(droppable).index();
          const isChild = this.get('data').objectAt(index).get('isChild');

          const screenX = this.get('_screenX');
          const newScreenX = event.originalEvent.screenX;

          if (!screenX) {
            this.set('_screenX', newScreenX);
          } else {
            const deltaX = newScreenX - screenX;
            const nestTolerance = this.get('nestTolerance');

            if (deltaX < (-1 * nestTolerance)) {
              // outdent
              droppable.removeClass('nesting');
              if (isChild) {
                droppable.removeClass('nested');
              }
            } else if (deltaX > nestTolerance) {
              // indent
              droppable.addClass('nesting');
            }
          }
        }
      }

    });

    this.$().on('dragleave.karbonsortable', (event) => {
      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable--enter');

      if (droppable.length === 1) {
        droppable.removeClass('droppable--enter');
        if (this.get('nestingAllowed')) {
          const index = Ember.$(droppable).index();
          const isChild = this.get('data').objectAt(index).get('isChild');

          droppable.removeClass('nesting');
          if (isChild) {
            droppable.addClass('nested');
          }
        }
      }
    });

    this.$().on('drop.karbonsortable', (event) => {
      event.preventDefault();

      const item = Ember.$(event.target);
      const droppable = item.closest('.droppable--enter');
      let isChild = false;
      let isSame = false;

      if (droppable.length === 1) {
        let newIndex = Ember.$(droppable).index();

        const dragged = this.get('_draggedEl');

        // need a better equality test
        if (dragged.id === droppable[0].id) {
          isSame = true;
        }

        // nesting will not be allowed if the drop is for a parent
        if (this.get('nestingAllowed')) {
          const screenX = this.get('_screenX');
          const newScreenX = event.originalEvent.screenX;
          const deltaX = newScreenX - screenX;
          const nestTolerance = this.get('nestTolerance');

          if (deltaX > nestTolerance || droppable.hasClass('nesting')) {
            // indent
            dragged.classList.add('nested');
            isChild = true;
          } else if (deltaX < (-1 * nestTolerance)) {
            // outdent
            dragged.classList.remove('nested');
          }

          if (!isSame && this.get('data').objectAt(newIndex).get('isChild')) {
            droppable.addClass('nested');
          }

          droppable.removeClass('nesting');
        }

        const oldIndex = Ember.$(dragged).index();
        const data = this.get('data');
        const dataItem = data.objectAt(oldIndex);

        droppable.removeClass('droppable--enter');

        const children = this.get('_dragGroup');

        // Move the data, have to keep the list in sync
        if (!isSame) {
          data.removeAt(oldIndex);
          data.insertAt(newIndex, dataItem);

          if (children) {
            // dragging down
            if (newIndex > oldIndex) {
              for (let i = 1; i <= children.length; i++) {
                let child = data.objectAt(oldIndex);

                data.removeAt(oldIndex);
                data.insertAt(newIndex, child);
              }
            } else {
              // dragging up
              for (let i = 1; i <= children.length; i++) {
                let child = data.objectAt(oldIndex + i);

                data.removeAt(oldIndex + i);
                data.insertAt(newIndex + i, child);
              }
            }

            Ember.run.later( () => {
              if (children) {
                children.forEach( (child) => {
                  let childEl = Ember.$(child);
                  childEl.removeClass('dragging');
                  childEl.addClass('droppable');
                });
              }
            }, 200);

          }
        }

        this.set('_dragGroup', null);

        dataItem.set('isChild', isChild);

        this.get('onOrderChanged')(dataItem, oldIndex, newIndex, isChild);
      }
    });
  },

  willDestroyElement() {
    this.$().off('dragstart.karbonsortable');
    this.$().off('dragend.karbonsortable');
    this.$().off('dragenter.karbonsortable');
    this.$().off('dragover.karbonsortable');
    this.$().off('dragleave.karbonsortable');
    this.$().off('drop.karbonsortable');
  }
});
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var sdk = require('../../../index');
var dis = require('../../../dispatcher');
var Signup = require("../../../Signup");
var ServerConfig = require("../../views/login/ServerConfig");
var MatrixClientPeg = require("../../../MatrixClientPeg");
var RegistrationForm = require("../../views/login/RegistrationForm");
var CaptchaForm = require("../../views/login/CaptchaForm");
var RtsClient = require("../../../RtsClient");

var MIN_PASSWORD_LENGTH = 6;

/**
 * TODO: It would be nice to make use of the InteractiveAuthEntryComponents
 * here, rather than inventing our own.
 */
module.exports = React.createClass({
    displayName: 'Registration',

    propTypes: {
        onLoggedIn: React.PropTypes.func.isRequired,
        clientSecret: React.PropTypes.string,
        sessionId: React.PropTypes.string,
        registrationUrl: React.PropTypes.string,
        idSid: React.PropTypes.string,
        customHsUrl: React.PropTypes.string,
        customIsUrl: React.PropTypes.string,
        defaultHsUrl: React.PropTypes.string,
        defaultIsUrl: React.PropTypes.string,
        brand: React.PropTypes.string,
        email: React.PropTypes.string,
        referrer: React.PropTypes.string,
        username: React.PropTypes.string,
        guestAccessToken: React.PropTypes.string,
        teamServerConfig: React.PropTypes.shape({
            // Email address to request new teams
            supportEmail: React.PropTypes.string.isRequired,
            // URL of the riot-team-server to get team configurations and track referrals
            teamServerURL: React.PropTypes.string.isRequired,
        }),
        teamSelected: React.PropTypes.object,
        onTeamMemberRegistered: React.PropTypes.func.isRequired,

        defaultDeviceDisplayName: React.PropTypes.string,

        // registration shouldn't know or care how login is done.
        onLoginClick: React.PropTypes.func.isRequired,
        onCancelClick: React.PropTypes.func
    },

    getInitialState: function() {
        return {
            busy: false,
            teamServerBusy: false,
            errorText: null,
            // We remember the values entered by the user because
            // the registration form will be unmounted during the
            // course of registration, but if there's an error we
            // want to bring back the registration form with the
            // values the user entered still in it. We can keep
            // them in this component's state since this component
            // persist for the duration of the registration process.
            formVals: {
                email: this.props.email,
            },
        };
    },

    componentWillMount: function() {
        this._unmounted = false;
        this.dispatcherRef = dis.register(this.onAction);
        // attach this to the instance rather than this.state since it isn't UI
        this.registerLogic = new Signup.Register(
            this.props.customHsUrl, this.props.customIsUrl, {
                defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
            }
        );
        this.registerLogic.setClientSecret(this.props.clientSecret);
        this.registerLogic.setSessionId(this.props.sessionId);
        this.registerLogic.setRegistrationUrl(this.props.registrationUrl);
        this.registerLogic.setIdSid(this.props.idSid);
        this.registerLogic.setGuestAccessToken(this.props.guestAccessToken);
        if (this.props.referrer) {
            this.registerLogic.setReferrer(this.props.referrer);
        }
        this.registerLogic.recheckState();

        if (
            this.props.teamServerConfig &&
            this.props.teamServerConfig.teamServerURL &&
            !this._rtsClient
        ) {
            this._rtsClient = new RtsClient(this.props.teamServerConfig.teamServerURL);

            this.setState({
                teamServerBusy: true,
            });
            // GET team configurations including domains, names and icons
            this._rtsClient.getTeamsConfig().then((data) => {
                const teamsConfig = {
                    teams: data,
                    supportEmail: this.props.teamServerConfig.supportEmail,
                };
                console.log('Setting teams config to ', teamsConfig);
                this.setState({
                    teamsConfig: teamsConfig,
                    teamServerBusy: false,
                });
            }, (err) => {
                console.error('Error retrieving config for teams', err);
                this.setState({
                    teamServerBusy: false,
                });
            });
        }
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
        this._unmounted = true;
    },

    componentDidMount: function() {
        // may have already done an HTTP hit (e.g. redirect from an email) so
        // check for any pending response
        var promise = this.registerLogic.getPromise();
        if (promise) {
            this.onProcessingRegistration(promise);
        }
    },

    onHsUrlChanged: function(newHsUrl) {
        this.registerLogic.setHomeserverUrl(newHsUrl);
    },

    onIsUrlChanged: function(newIsUrl) {
        this.registerLogic.setIdentityServerUrl(newIsUrl);
    },

    onAction: function(payload) {
        if (payload.action !== "registration_step_update") {
            return;
        }
        // If the registration state has changed, this means the
        // user now needs to do something. It would be better
        // to expose the explicitly in the register logic.
        this.setState({
            busy: false
        });
    },

    onFormSubmit: function(formVals) {
        var self = this;
        this.setState({
            errorText: "",
            busy: true,
            formVals: formVals,
        });

        if (formVals.username !== this.props.username) {
            // don't try to upgrade if we changed our username
            this.registerLogic.setGuestAccessToken(null);
        }

        this.onProcessingRegistration(this.registerLogic.register(formVals));
    },

    // Promise is resolved when the registration process is FULLY COMPLETE
    onProcessingRegistration: function(promise) {
        var self = this;
        promise.done(function(response) {
            self.setState({
                busy: false
            });
            if (!response || !response.access_token) {
                console.warn(
                    "FIXME: Register fulfilled without a final response, " +
                    "did you break the promise chain?"
                );
                // no matter, we'll grab it direct
                response = self.registerLogic.getCredentials();
            }
            if (!response || !response.user_id || !response.access_token) {
                console.error("Final response is missing keys.");
                self.setState({
                    errorText: "Registration failed on server"
                });
                return;
            }
            self.props.onLoggedIn({
                userId: response.user_id,
                deviceId: response.device_id,
                homeserverUrl: self.registerLogic.getHomeserverUrl(),
                identityServerUrl: self.registerLogic.getIdentityServerUrl(),
                accessToken: response.access_token
            });

            // Done regardless of `teamSelected`. People registering with non-team emails
            // will just nop. The point of this being we might not have the email address
            // that the user registered with at this stage (depending on whether this
            // is the client they initiated registration).
            if (
                self._rtsClient &&
                self.props.referrer
            ) {
                // Track referral, get team_token in order to retrieve team config
                self._rtsClient.trackReferral(
                    self.props.referrer,
                    self.registerLogic.params.idSid,
                    self.registerLogic.params.clientSecret
                ).then((data) => {
                    const teamToken = data.team_token;
                    // Store for use /w welcome pages
                    window.localStorage.setItem('mx_team_token', teamToken);
                    self.props.onTeamMemberRegistered(teamToken);

                    self._rtsClient.getTeam(teamToken).then((team) => {
                        console.log(
                            `User successfully registered with team ${team.name}`
                        );
                        if (!team.rooms) {
                            return;
                        }
                        // Auto-join rooms
                        team.rooms.forEach((room) => {
                            if (room.auto_join && room.room_id) {
                                console.log(`Auto-joining ${room.room_id}`);
                                MatrixClientPeg.get().joinRoom(room.room_id);
                            }
                        });
                    }, (err) => {
                        console.error('Error getting team config', err);
                    });
                }, (err) => {
                    console.error('Error tracking referral', err);
                });
            }

            if (self.props.brand) {
                MatrixClientPeg.get().getPushers().done((resp)=>{
                    var pushers = resp.pushers;
                    for (var i = 0; i < pushers.length; ++i) {
                        if (pushers[i].kind == 'email') {
                            var emailPusher = pushers[i];
                            emailPusher.data = { brand: self.props.brand };
                            MatrixClientPeg.get().setPusher(emailPusher).done(() => {
                                console.log("Set email branding to " + self.props.brand);
                            }, (error) => {
                                console.error("Couldn't set email branding: " + error);
                            });
                        }
                    }
                }, (error) => {
                    console.error("Couldn't get pushers: " + error);
                });
            }

        }, function(err) {
            if (err.message) {
                self.setState({
                    errorText: err.message
                });
            }
            self.setState({
                busy: false
            });
            console.log(err);
        });
    },

    onFormValidationFailed: function(errCode) {
        var errMsg;
        switch (errCode) {
            case "RegistrationForm.ERR_PASSWORD_MISSING":
                errMsg = "Missing password.";
                break;
            case "RegistrationForm.ERR_PASSWORD_MISMATCH":
                errMsg = "Passwords don't match.";
                break;
            case "RegistrationForm.ERR_PASSWORD_LENGTH":
                errMsg = `Password too short (min ${MIN_PASSWORD_LENGTH}).`;
                break;
            case "RegistrationForm.ERR_EMAIL_INVALID":
                errMsg = "This doesn't look like a valid email address";
                break;
            case "RegistrationForm.ERR_USERNAME_INVALID":
                errMsg = "User names may only contain letters, numbers, dots, hyphens and underscores.";
                break;
            case "RegistrationForm.ERR_USERNAME_BLANK":
                errMsg = "You need to enter a user name";
                break;
            default:
                console.error("Unknown error code: %s", errCode);
                errMsg = "An unknown error occurred.";
                break;
        }
        this.setState({
            errorText: errMsg
        });
    },

    onCaptchaResponse: function(response) {
        this.registerLogic.tellStage("m.login.recaptcha", {
            response: response
        });
    },

    onTeamSelected: function(teamSelected) {
        if (!this._unmounted) {
            this.setState({ teamSelected });
        }
    },

    _getRegisterContentJsx: function() {
        const Spinner = sdk.getComponent("elements.Spinner");

        var currStep = this.registerLogic.getStep();
        var registerStep;
        switch (currStep) {
            case "Register.COMPLETE":
                break; // NOP
            case "Register.START":
            case "Register.STEP_m.login.dummy":
                // NB. Our 'username' prop is specifically for upgrading
                // a guest account
                if (this.state.teamServerBusy) {
                    registerStep = <Spinner />;
                    break;
                }
                registerStep = (
                    <RegistrationForm
                        showEmail={true}
                        defaultUsername={this.state.formVals.username}
                        defaultEmail={this.state.formVals.email}
                        defaultPassword={this.state.formVals.password}
                        teamsConfig={this.state.teamsConfig}
                        guestUsername={this.props.username}
                        minPasswordLength={MIN_PASSWORD_LENGTH}
                        onError={this.onFormValidationFailed}
                        onRegisterClick={this.onFormSubmit}
                        onTeamSelected={this.onTeamSelected}
                    />
                );
                break;
            case "Register.STEP_m.login.email.identity":
                registerStep = (

                        Please check your email to continue registration.

                );
                break;
            case "Register.STEP_m.login.recaptcha":
                var publicKey;
                var serverParams = this.registerLogic.getServerData().params;
                if (serverParams && serverParams["m.login.recaptcha"]) {
                    publicKey = serverParams["m.login.recaptcha"].public_key;
                }

                registerStep = (
                    <CaptchaForm sitePublicKey={publicKey}
                        onCaptchaResponse={this.onCaptchaResponse}
                    />
                );
                break;
            default:
                console.error("Unknown register state: %s", currStep);
                break;
        }
        var busySpinner;
        if (this.state.busy) {
            busySpinner = (
                <Spinner />
            );
        }

        var returnToAppJsx;
        if (this.props.onCancelClick) {
            returnToAppJsx =

                    Return to app
                ;
        }

        return (

Create an account

                {registerStep}

{this.state.errorText}

                {busySpinner}
                <ServerConfig ref="serverConfig"
                    withToggleButton={ this.registerLogic.getStep() === "Register.START" }
                    customHsUrl={this.props.customHsUrl}
                    customIsUrl={this.props.customIsUrl}
                    defaultHsUrl={this.props.defaultHsUrl}
                    defaultIsUrl={this.props.defaultIsUrl}
                    onHsUrlChanged={this.onHsUrlChanged}
                    onIsUrlChanged={this.onIsUrlChanged}
                    delayTimeMs={1000} />

                    I already have an account

                { returnToAppJsx }

        );
    },

    render: function() {
        var LoginHeader = sdk.getComponent('login.LoginHeader');
        var LoginFooter = sdk.getComponent('login.LoginFooter');
        return (

                    <LoginHeader
                        icon={this.state.teamSelected ?
                            this.props.teamServerConfig.teamServerURL + "/static/common/" +
                            this.state.teamSelected.domain + "/icon.png" :
                            null}
                    />
                    {this._getRegisterContentJsx()}
                    <LoginFooter />

        );
    }
});
<commit_msg>If a referrer hasn't been specified, use empty string<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var sdk = require('../../../index');
var dis = require('../../../dispatcher');
var Signup = require("../../../Signup");
var ServerConfig = require("../../views/login/ServerConfig");
var MatrixClientPeg = require("../../../MatrixClientPeg");
var RegistrationForm = require("../../views/login/RegistrationForm");
var CaptchaForm = require("../../views/login/CaptchaForm");
var RtsClient = require("../../../RtsClient");

var MIN_PASSWORD_LENGTH = 6;

/**
 * TODO: It would be nice to make use of the InteractiveAuthEntryComponents
 * here, rather than inventing our own.
 */
module.exports = React.createClass({
    displayName: 'Registration',

    propTypes: {
        onLoggedIn: React.PropTypes.func.isRequired,
        clientSecret: React.PropTypes.string,
        sessionId: React.PropTypes.string,
        registrationUrl: React.PropTypes.string,
        idSid: React.PropTypes.string,
        customHsUrl: React.PropTypes.string,
        customIsUrl: React.PropTypes.string,
        defaultHsUrl: React.PropTypes.string,
        defaultIsUrl: React.PropTypes.string,
        brand: React.PropTypes.string,
        email: React.PropTypes.string,
        referrer: React.PropTypes.string,
        username: React.PropTypes.string,
        guestAccessToken: React.PropTypes.string,
        teamServerConfig: React.PropTypes.shape({
            // Email address to request new teams
            supportEmail: React.PropTypes.string.isRequired,
            // URL of the riot-team-server to get team configurations and track referrals
            teamServerURL: React.PropTypes.string.isRequired,
        }),
        teamSelected: React.PropTypes.object,
        onTeamMemberRegistered: React.PropTypes.func.isRequired,

        defaultDeviceDisplayName: React.PropTypes.string,

        // registration shouldn't know or care how login is done.
        onLoginClick: React.PropTypes.func.isRequired,
        onCancelClick: React.PropTypes.func
    },

    getInitialState: function() {
        return {
            busy: false,
            teamServerBusy: false,
            errorText: null,
            // We remember the values entered by the user because
            // the registration form will be unmounted during the
            // course of registration, but if there's an error we
            // want to bring back the registration form with the
            // values the user entered still in it. We can keep
            // them in this component's state since this component
            // persist for the duration of the registration process.
            formVals: {
                email: this.props.email,
            },
        };
    },

    componentWillMount: function() {
        this._unmounted = false;
        this.dispatcherRef = dis.register(this.onAction);
        // attach this to the instance rather than this.state since it isn't UI
        this.registerLogic = new Signup.Register(
            this.props.customHsUrl, this.props.customIsUrl, {
                defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
            }
        );
        this.registerLogic.setClientSecret(this.props.clientSecret);
        this.registerLogic.setSessionId(this.props.sessionId);
        this.registerLogic.setRegistrationUrl(this.props.registrationUrl);
        this.registerLogic.setIdSid(this.props.idSid);
        this.registerLogic.setGuestAccessToken(this.props.guestAccessToken);
        if (this.props.referrer) {
            this.registerLogic.setReferrer(this.props.referrer);
        }
        this.registerLogic.recheckState();

        if (
            this.props.teamServerConfig &&
            this.props.teamServerConfig.teamServerURL &&
            !this._rtsClient
        ) {
            this._rtsClient = new RtsClient(this.props.teamServerConfig.teamServerURL);

            this.setState({
                teamServerBusy: true,
            });
            // GET team configurations including domains, names and icons
            this._rtsClient.getTeamsConfig().then((data) => {
                const teamsConfig = {
                    teams: data,
                    supportEmail: this.props.teamServerConfig.supportEmail,
                };
                console.log('Setting teams config to ', teamsConfig);
                this.setState({
                    teamsConfig: teamsConfig,
                    teamServerBusy: false,
                });
            }, (err) => {
                console.error('Error retrieving config for teams', err);
                this.setState({
                    teamServerBusy: false,
                });
            });
        }
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
        this._unmounted = true;
    },

    componentDidMount: function() {
        // may have already done an HTTP hit (e.g. redirect from an email) so
        // check for any pending response
        var promise = this.registerLogic.getPromise();
        if (promise) {
            this.onProcessingRegistration(promise);
        }
    },

    onHsUrlChanged: function(newHsUrl) {
        this.registerLogic.setHomeserverUrl(newHsUrl);
    },

    onIsUrlChanged: function(newIsUrl) {
        this.registerLogic.setIdentityServerUrl(newIsUrl);
    },

    onAction: function(payload) {
        if (payload.action !== "registration_step_update") {
            return;
        }
        // If the registration state has changed, this means the
        // user now needs to do something. It would be better
        // to expose the explicitly in the register logic.
        this.setState({
            busy: false
        });
    },

    onFormSubmit: function(formVals) {
        var self = this;
        this.setState({
            errorText: "",
            busy: true,
            formVals: formVals,
        });

        if (formVals.username !== this.props.username) {
            // don't try to upgrade if we changed our username
            this.registerLogic.setGuestAccessToken(null);
        }

        this.onProcessingRegistration(this.registerLogic.register(formVals));
    },

    // Promise is resolved when the registration process is FULLY COMPLETE
    onProcessingRegistration: function(promise) {
        var self = this;
        promise.done(function(response) {
            self.setState({
                busy: false
            });
            if (!response || !response.access_token) {
                console.warn(
                    "FIXME: Register fulfilled without a final response, " +
                    "did you break the promise chain?"
                );
                // no matter, we'll grab it direct
                response = self.registerLogic.getCredentials();
            }
            if (!response || !response.user_id || !response.access_token) {
                console.error("Final response is missing keys.");
                self.setState({
                    errorText: "Registration failed on server"
                });
                return;
            }
            self.props.onLoggedIn({
                userId: response.user_id,
                deviceId: response.device_id,
                homeserverUrl: self.registerLogic.getHomeserverUrl(),
                identityServerUrl: self.registerLogic.getIdentityServerUrl(),
                accessToken: response.access_token
            });

            // Done regardless of `teamSelected`. People registering with non-team emails
            // will just nop. The point of this being we might not have the email address
            // that the user registered with at this stage (depending on whether this
            // is the client they initiated registration).
            if (self._rtsClient) {
                // Track referral if self.props.referrer set, get team_token in order to
                // retrieve team config and see welcome page etc.
                self._rtsClient.trackReferral(
                    self.props.referrer || '', // Default to empty string = not referred
                    self.registerLogic.params.idSid,
                    self.registerLogic.params.clientSecret
                ).then((data) => {
                    const teamToken = data.team_token;
                    // Store for use /w welcome pages
                    window.localStorage.setItem('mx_team_token', teamToken);
                    self.props.onTeamMemberRegistered(teamToken);

                    self._rtsClient.getTeam(teamToken).then((team) => {
                        console.log(
                            `User successfully registered with team ${team.name}`
                        );
                        if (!team.rooms) {
                            return;
                        }
                        // Auto-join rooms
                        team.rooms.forEach((room) => {
                            if (room.auto_join && room.room_id) {
                                console.log(`Auto-joining ${room.room_id}`);
                                MatrixClientPeg.get().joinRoom(room.room_id);
                            }
                        });
                    }, (err) => {
                        console.error('Error getting team config', err);
                    });
                }, (err) => {
                    console.error('Error tracking referral', err);
                });
            }

            if (self.props.brand) {
                MatrixClientPeg.get().getPushers().done((resp)=>{
                    var pushers = resp.pushers;
                    for (var i = 0; i < pushers.length; ++i) {
                        if (pushers[i].kind == 'email') {
                            var emailPusher = pushers[i];
                            emailPusher.data = { brand: self.props.brand };
                            MatrixClientPeg.get().setPusher(emailPusher).done(() => {
                                console.log("Set email branding to " + self.props.brand);
                            }, (error) => {
                                console.error("Couldn't set email branding: " + error);
                            });
                        }
                    }
                }, (error) => {
                    console.error("Couldn't get pushers: " + error);
                });
            }

        }, function(err) {
            if (err.message) {
                self.setState({
                    errorText: err.message
                });
            }
            self.setState({
                busy: false
            });
            console.log(err);
        });
    },

    onFormValidationFailed: function(errCode) {
        var errMsg;
        switch (errCode) {
            case "RegistrationForm.ERR_PASSWORD_MISSING":
                errMsg = "Missing password.";
                break;
            case "RegistrationForm.ERR_PASSWORD_MISMATCH":
                errMsg = "Passwords don't match.";
                break;
            case "RegistrationForm.ERR_PASSWORD_LENGTH":
                errMsg = `Password too short (min ${MIN_PASSWORD_LENGTH}).`;
                break;
            case "RegistrationForm.ERR_EMAIL_INVALID":
                errMsg = "This doesn't look like a valid email address";
                break;
            case "RegistrationForm.ERR_USERNAME_INVALID":
                errMsg = "User names may only contain letters, numbers, dots, hyphens and underscores.";
                break;
            case "RegistrationForm.ERR_USERNAME_BLANK":
                errMsg = "You need to enter a user name";
                break;
            default:
                console.error("Unknown error code: %s", errCode);
                errMsg = "An unknown error occurred.";
                break;
        }
        this.setState({
            errorText: errMsg
        });
    },

    onCaptchaResponse: function(response) {
        this.registerLogic.tellStage("m.login.recaptcha", {
            response: response
        });
    },

    onTeamSelected: function(teamSelected) {
        if (!this._unmounted) {
            this.setState({ teamSelected });
        }
    },

    _getRegisterContentJsx: function() {
        const Spinner = sdk.getComponent("elements.Spinner");

        var currStep = this.registerLogic.getStep();
        var registerStep;
        switch (currStep) {
            case "Register.COMPLETE":
                break; // NOP
            case "Register.START":
            case "Register.STEP_m.login.dummy":
                // NB. Our 'username' prop is specifically for upgrading
                // a guest account
                if (this.state.teamServerBusy) {
                    registerStep = <Spinner />;
                    break;
                }
                registerStep = (
                    <RegistrationForm
                        showEmail={true}
                        defaultUsername={this.state.formVals.username}
                        defaultEmail={this.state.formVals.email}
                        defaultPassword={this.state.formVals.password}
                        teamsConfig={this.state.teamsConfig}
                        guestUsername={this.props.username}
                        minPasswordLength={MIN_PASSWORD_LENGTH}
                        onError={this.onFormValidationFailed}
                        onRegisterClick={this.onFormSubmit}
                        onTeamSelected={this.onTeamSelected}
                    />
                );
                break;
            case "Register.STEP_m.login.email.identity":
                registerStep = (

                        Please check your email to continue registration.

                );
                break;
            case "Register.STEP_m.login.recaptcha":
                var publicKey;
                var serverParams = this.registerLogic.getServerData().params;
                if (serverParams && serverParams["m.login.recaptcha"]) {
                    publicKey = serverParams["m.login.recaptcha"].public_key;
                }

                registerStep = (
                    <CaptchaForm sitePublicKey={publicKey}
                        onCaptchaResponse={this.onCaptchaResponse}
                    />
                );
                break;
            default:
                console.error("Unknown register state: %s", currStep);
                break;
        }
        var busySpinner;
        if (this.state.busy) {
            busySpinner = (
                <Spinner />
            );
        }

        var returnToAppJsx;
        if (this.props.onCancelClick) {
            returnToAppJsx =

                    Return to app
                ;
        }

        return (

Create an account

                {registerStep}

{this.state.errorText}

                {busySpinner}
                <ServerConfig ref="serverConfig"
                    withToggleButton={ this.registerLogic.getStep() === "Register.START" }
                    customHsUrl={this.props.customHsUrl}
                    customIsUrl={this.props.customIsUrl}
                    defaultHsUrl={this.props.defaultHsUrl}
                    defaultIsUrl={this.props.defaultIsUrl}
                    onHsUrlChanged={this.onHsUrlChanged}
                    onIsUrlChanged={this.onIsUrlChanged}
                    delayTimeMs={1000} />

                    I already have an account

                { returnToAppJsx }

        );
    },

    render: function() {
        var LoginHeader = sdk.getComponent('login.LoginHeader');
        var LoginFooter = sdk.getComponent('login.LoginFooter');
        return (

                    <LoginHeader
                        icon={this.state.teamSelected ?
                            this.props.teamServerConfig.teamServerURL + "/static/common/" +
                            this.state.teamSelected.domain + "/icon.png" :
                            null}
                    />
                    {this._getRegisterContentJsx()}
                    <LoginFooter />

        );
    }
});
<|endoftext|>


<commit_before>'use strict';

function guess(){
    if(!guessing){
        return;
    }

    var guessvalue = parseInt(
      document.getElementById('guess-input').value,
      10
    );

    // If the guess is not a number or not in guessing range.
    if(isNaN(guessvalue)
      || guessvalue.length < 1
      || guessvalue > max
      || guessvalue < min){
        document.getElementById('info').innerHTML =
          'You must enter an integer between ' + min + ' and ' + max + ', inclusive.';
        return;
    }

    document.getElementById('guess-input').value = guessvalue;
    var result = '';

    // Check if valid guess is lower than value.
    if(guessvalue > value){
        result = 'LOWER';

    // Check if valid guess is higher than value.
    }else if(guessvalue < value){
        result = 'HIGHER';

    // Only option left is guess is correct.
    }else{
        guessing = false;
        result = 'CORRECT! YOU WIN!';
    }

    document.getElementById('guesses').innerHTML = parseInt(
      document.getElementById('guesses').innerHTML,
      10
    ) + 1;
    document.getElementById('info').innerHTML = result;
}

function new_game(skip){
    if(!skip
      && !window.confirm('Start new game?')){
        return;
    }

    document.getElementById('guess-input').value = '';
    document.getElementById('guesses').innerHTML = 0;
    document.getElementById('info').innerHTML = '';
    guessing = true;

    // Generate new value to guess.
    value = core_random_integer({
      'max': max - min
    }) + min;
}

function repo_init(){
    core_repo_init({
      'keybinds': {
        13: {
          'todo': guess,
        },
        78: {
          'todo': function(){
              new_game(false);
          },
        },
      },
      'title': 'Guess.htm',
    });

    document.getElementById('guess-max').value = max;
    document.getElementById('guess-min').value = min;

    new_game(true);

    document.getElementById('guess-button').onclick = guess;
    document.getElementById('guess-max').oninput = set_value;
    document.getElementById('guess-min').oninput = set_value;
    document.getElementById('new-game').onclick = function(){
        new_game(false);
    };
}

function set_value(){
    var newmax = parseInt(document.getElementById('guess-max').value, 10);
    var newmin = parseInt(document.getElementById('guess-min').value, 10);

    if(isNan(min)){
        min = 1;
    }
    if(isNan(max)){
        max = 1000000;
    }
    if(min > max){
        min = max;
    }

    new_game(true);
}

var guessing = true;
var max = 1000000;
var min = 1;
var value = 0;
<commit_msg>added core menu usage<commit_after>'use strict';

function guess(){
    if(!guessing){
        return;
    }

    var guessvalue = parseInt(
      document.getElementById('guess-input').value,
      10
    );

    // If the guess is not a number or not in guessing range.
    if(isNaN(guessvalue)
      || guessvalue.length < 1
      || guessvalue > max
      || guessvalue < min){
        document.getElementById('info').innerHTML =
          'You must enter an integer between ' + min + ' and ' + max + ', inclusive.';
        return;
    }

    document.getElementById('guess-input').value = guessvalue;
    var result = '';

    // Check if valid guess is lower than value.
    if(guessvalue > value){
        result = 'LOWER';

    // Check if valid guess is higher than value.
    }else if(guessvalue < value){
        result = 'HIGHER';

    // Only option left is guess is correct.
    }else{
        guessing = false;
        result = 'CORRECT! YOU WIN!';
    }

    document.getElementById('guesses').innerHTML = parseInt(
      document.getElementById('guesses').innerHTML,
      10
    ) + 1;
    document.getElementById('info').innerHTML = result;
}

function new_game(skip){
    if(!skip
      && !window.confirm('Start new game?')){
        return;
    }

    document.getElementById('guess-input').value = '';
    document.getElementById('guesses').innerHTML = 0;
    document.getElementById('info').innerHTML = '';
    guessing = true;

    // Generate new value to guess.
    value = core_random_integer({
      'max': max - min
    }) + min;
}

function repo_init(){
    core_repo_init({
      'keybinds': {
        13: {
          'todo': guess,
        },
        78: {
          'todo': function(){
              new_game(false);
          },
        },
      },
      'title': 'Guess.htm',
    });

    document.getElementById('guess-max').value = max;
    document.getElementById('guess-min').value = min;

    new_game(true);

    document.getElementById('guess-button').onclick = guess;
    document.getElementById('guess-max').oninput = set_value;
    document.getElementById('guess-min').oninput = set_value;
    document.getElementById('new-game').onclick = function(){
        new_game(false);
    };
}

function set_value(){
    var newmax = parseInt(document.getElementById('guess-max').value, 10);
    var newmin = parseInt(document.getElementById('guess-min').value, 10);

    if(isNaN(min)){
        min = 1;
    }
    if(isNaN(max)){
        max = 1000000;
    }
    if(min > max){
        min = max;
    }

    new_game(true);
}

var guessing = true;
var max = 1000000;
var min = 1;
var value = 0;
<|endoftext|>


<commit_before>var selectify = require('./index.js')

var selection = selectify([
  {id: 'apple', className: 'fruit'},
  {id: 'orange', className: 'fruit'}
])

selection.style({color: 'rgb(255, 0, 0)'})

selection.classed('citrus', function (d) {return d.id === 'orange'})

selection.each(function (d) {
  console.log('id: ' + d.id)
  console.log('style: ' + JSON.stringify(d.style))
  console.log('class: ' + d.className)
})
<commit_msg>formatting<commit_after>var selectify = require('./index.js')

var selection = selectify([
  {id: 'apple', className: 'fruit'},
  {id: 'orange', className: 'fruit'}
])

selection.style({color: 'rgb(255, 0, 0)'})

selection.classed('citrus', function (d) { return d.id === 'orange' })

selection.each(function (d) {
  console.log('id: ' + d.id)
  console.log('style: ' + JSON.stringify(d.style))
  console.log('class: ' + d.className)
})
<|endoftext|>