<commit_before>// Category View
// =============

// Includes file dependencies
define([
    "jquery",
    "backbone",
    "moment",
    "text!../templates/character-print-view.html",
    "text!../templates/character-approval-view.html",
    "../collections/Approvals",
    "../models/Approval",
    "text!../templates/character-approval-selected-view.html",
    "../helpers/VampirePrintHelper"
], function( $,
             Backbone,
             moment,
             character_print_view_html,
             character_approval_view_html,
             Approvals,
             Approval,
             character_approval_selected_view_html,
             VampirePrintHelper) {

    // Extends Backbone.View
    var View = Backbone.View.extend( {

        // The View Constructor
        initialize: function() {
            var self = this;

            _.bindAll(this,
                "render",
                "format_simpletext",
                "format_attribute_value",
                "format_attribute_focus",
                "format_skill",
                "format_specializations"
            );

            self.sheetTemplate = _.template(character_print_view_html);
            self.approvalSelectedTemplate = _.template(character_approval_selected_view_html);
        },

        register: function(character) {
            var self = this;
            var p = Parse.Promise.as([]);

            if (character !== self.character) {
                if (self.character) {
                    self.stopListening(self.character);
                    if (self.character.recorded_changes) {
                        self.stopListening(self.character.recorded_changes);
                    }
                }
                self.character = character;

                self.approvals = new Approvals;
                var q = new Parse.Query(Approval);
                q.equalTo("owner", self.character);
                self.approvals.query = q;
                p = q.each(function (approval) {
                    self.approvals.add(approval);
                    self.approval_index = self.approvals.length;
                });
                p.then(function () {
                    return self.character.get_recorded_changes(function (rc) {
                        self.listenTo(rc, "add", self.render);
                        self.listenTo(rc, "reset", self.render);
                        if (self.character.recorded_changes.length > 0) {
                            _.defer(self.render);
                        }
                    });
                });
            }

            return p.then(function () {
                Parse.Promise.as(self);
            });
        },

        events: {
            "change #slider": "update_selected",
            "change #sliderbaserange": "update_base_selected",
            "change #approval-slider": "update_approval_selected",
            "click .approve-change": "approve_change"
        },

        approve_change: function() {
            var self = this;
            var change = self.character.recorded_changes.at(self.idForPickedIndex);
            var approval = new Approval({
                approved: true,
                change: change,
                approver: Parse.User.current(),
                owner: self.character
            });
            return approval.save();
        },

        format_entry: function(log, entry) {
            if (_.isUndefined(log)) {
                console.log("Undefined log");
                return "Undefined log";
            }
            if (log.get(entry)) {
                return log.get(entry);
            }
            var attr = log[entry];
            if (_.isDate(attr)) {
                return moment(attr).format('lll');
            }
            return attr;
        },

        format_approval: function(approval, h) {
            var sub = approval.get(h);
            if (_.isUndefined(sub)) {
                return _.result(approval, h);
            }
            if (_.has(sub, "id")) {
                return sub.id;
            }
            return sub;
        },

        _update_approval_selected: function (selectedIndex) {
            var self = this;
            self.approval_index = selectedIndex;
            self.approved = self.approvals.models[self.approval_index];
            self.left_approval_index = self.approval_index - 1
            if (self.left_approval_index >= 0) {
                self.left_approved = self.approvals.models[self.left_approval_index];
            } else {
                self.left_approved = null;
            }

            var selectedIndex = 0;
            if (self.approval_index < self.approvals.length) {
                var change = _.findLast(self.character.recorded_changes.models, function (model, i) {
                    if (model.id == self.approved.get("change").id) {
                        selectedIndex = i;
                        return true;
                    }
                    return false;
                })
            } else {
                selectedIndex = self.character.recorded_changes.length - 1;
            }
            self.idForPickedIndex = selectedIndex;
            if (self.left_approval_index >= 0) {
                _.findLast(self.character.recorded_changes.models, function (model, i) {
                    if (model.id == self.left_approved.get("change").id) {
                        self.left_rc_index = i + 1;
                        return true;
                    }
                    return false;
                });
            } else {
                self.left_rc_index = 0;
            }

            self.$("#slider").val(selectedIndex).slider('refresh');
            self.$("#sliderbaserange").val(self.left_rc_index).slider('refresh');

            return change || _.last(self.character.recorded_changes.models);
        },

        update_approval_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            var change = self._update_approval_selected(selectedIndex);

            self._render_viewing(true);

            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != change.id;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self._render_sheet(c, true);
        },

        update_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.idForPickedIndex = selectedIndex;
            self._render_viewing(true);

            var selectedId = this.$("#history-changes-" + selectedIndex).val();
            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != selectedId;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self._render_sheet(c, true);
        },

        update_base_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.left_rc_index = selectedIndex;
            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model, i) {
                return i != selectedIndex;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self.transform_description = c.transform_description;
            self._render_viewing(true);
            self._render_sheet();
        },

        _render_viewing: function(enhance) {
            var self = this;
            var sendId = self.idForPickedIndex;
            if (_.isUndefined(sendId)) {
                sendId = self.character.recorded_changes.models.length - 1;
            }
            this.$el.find("#approval-viewing").html(this.approvalSelectedTemplate({
                "character": this.character,
                "logs": self.character.recorded_changes.models,
                "format_entry": this.format_entry,
                "format_approval": this.format_approval,
                idForPickedIndex: sendId,
                left_rc_index: self.left_rc_index,
                approval_index: self.approval_index,
                approvals: self.approvals.models,
                approval: self.approvals.models[self.approval_index]
            }));
            if (enhance) {
                this.$el.find("#approval-viewing").enhanceWithin();
            }
        },

        _render_sheet: function(characterOverride, enhance) {
            var self = this;
            var c = characterOverride || self.character;
            var sortedSkills = c.get_sorted_skills();
            var groupedSkills = c.get_grouped_skills(sortedSkills, 3);
            this.$el.find("#approval-sheet").html(this.sheetTemplate({
                "character": c,
                "skills": sortedSkills,
                "groupedSkills": groupedSkills,
                "transform_description": self.transform_description,
                format_simpletext: this.format_simpletext,
                format_attribute_value: this.format_attribute_value,
                format_attribute_focus: this.format_attribute_focus,
                format_skill: this.format_skill,
                format_specializations: this.format_specializations,
            }));
            if (enhance) {
                this.$el.find("#approval-sheet").enhanceWithin();
            }
        },

        // Renders all of the Category models on the UI
        render: function() {
            var self = this;

            var sendId = self.idForPickedIndex;
            if (_.isUndefined(sendId)) {
                sendId = self.character.recorded_changes.models.length - 1;
            }

            self._update_approval_selected(self.approvals.length);

            // Sets the view's template property
            this.template = _.template(character_approval_view_html)({
                    "character": this.character,
                    "logs": this.character.recorded_changes.models,
                    "format_entry": this.format_entry,
                    "format_approval": this.format_approval,
                    idForPickedIndex: sendId,
                    left_rc_index: self.left_rc_index,
                    approval_index: self.approval_index,
                    approvals: self.approvals.models,
                    approval: self.approvals.models[self.approval_index]
                 });

            /*
            _.each(self.approvals.models[self.approval_index], function (approval, i) {
                var headers = ["approved", "change", "approver", "owner"];
                _.each(headers, function (h) {
                    console.log(approval.get(h));
                });
            });
            */
            // Renders the view's template inside of the current listview element
            this.$el.find("#approval-main").html(this.template);

            this._render_viewing();

            this._render_sheet();

            this.$el.enhanceWithin();

            // Maintains chainability
            return this;

        }

    } );

    _.extend(View.prototype, VampirePrintHelper);

    // Returns the View class
    return View;

} );<commit_msg>Initialize transform description on load<commit_after>// Category View
// =============

// Includes file dependencies
define([
    "jquery",
    "backbone",
    "moment",
    "text!../templates/character-print-view.html",
    "text!../templates/character-approval-view.html",
    "../collections/Approvals",
    "../models/Approval",
    "text!../templates/character-approval-selected-view.html",
    "../helpers/VampirePrintHelper"
], function( $,
             Backbone,
             moment,
             character_print_view_html,
             character_approval_view_html,
             Approvals,
             Approval,
             character_approval_selected_view_html,
             VampirePrintHelper) {

    // Extends Backbone.View
    var View = Backbone.View.extend( {

        // The View Constructor
        initialize: function() {
            var self = this;

            _.bindAll(this,
                "render",
                "format_simpletext",
                "format_attribute_value",
                "format_attribute_focus",
                "format_skill",
                "format_specializations"
            );

            self.sheetTemplate = _.template(character_print_view_html);
            self.approvalSelectedTemplate = _.template(character_approval_selected_view_html);
        },

        register: function(character) {
            var self = this;
            var p = Parse.Promise.as([]);

            if (character !== self.character) {
                if (self.character) {
                    self.stopListening(self.character);
                    if (self.character.recorded_changes) {
                        self.stopListening(self.character.recorded_changes);
                    }
                }
                self.character = character;

                self.approvals = new Approvals;
                var q = new Parse.Query(Approval);
                q.equalTo("owner", self.character);
                self.approvals.query = q;
                p = q.each(function (approval) {
                    self.approvals.add(approval);
                    self.approval_index = self.approvals.length;
                });
                p.then(function () {
                    return self.character.get_recorded_changes(function (rc) {
                        self.listenTo(rc, "add", self.render);
                        self.listenTo(rc, "reset", self.render);
                        if (self.character.recorded_changes.length > 0) {
                            _.defer(self.render);
                        }
                    });
                });
            }

            return p.then(function () {
                Parse.Promise.as(self);
            });
        },

        events: {
            "change #slider": "update_selected",
            "change #sliderbaserange": "update_base_selected",
            "change #approval-slider": "update_approval_selected",
            "click .approve-change": "approve_change"
        },

        approve_change: function() {
            var self = this;
            var change = self.character.recorded_changes.at(self.idForPickedIndex);
            var approval = new Approval({
                approved: true,
                change: change,
                approver: Parse.User.current(),
                owner: self.character
            });
            return approval.save();
        },

        format_entry: function(log, entry) {
            if (_.isUndefined(log)) {
                console.log("Undefined log");
                return "Undefined log";
            }
            if (log.get(entry)) {
                return log.get(entry);
            }
            var attr = log[entry];
            if (_.isDate(attr)) {
                return moment(attr).format('lll');
            }
            return attr;
        },

        format_approval: function(approval, h) {
            var sub = approval.get(h);
            if (_.isUndefined(sub)) {
                return _.result(approval, h);
            }
            if (_.has(sub, "id")) {
                return sub.id;
            }
            return sub;
        },

        _update_approval_selected: function (selectedIndex) {
            var self = this;
            self.approval_index = selectedIndex;
            self.approved = self.approvals.models[self.approval_index];
            self.left_approval_index = self.approval_index - 1
            if (self.left_approval_index >= 0) {
                self.left_approved = self.approvals.models[self.left_approval_index];
            } else {
                self.left_approved = null;
            }

            var selectedIndex = 0;
            if (self.approval_index < self.approvals.length) {
                var change = _.findLast(self.character.recorded_changes.models, function (model, i) {
                    if (model.id == self.approved.get("change").id) {
                        selectedIndex = i;
                        return true;
                    }
                    return false;
                })
            } else {
                selectedIndex = self.character.recorded_changes.length - 1;
            }
            self.idForPickedIndex = selectedIndex;
            if (self.left_approval_index >= 0) {
                _.findLast(self.character.recorded_changes.models, function (model, i) {
                    if (model.id == self.left_approved.get("change").id) {
                        self.left_rc_index = i + 1;
                        return true;
                    }
                    return false;
                });
            } else {
                self.left_rc_index = 0;
            }

            self.$("#slider").val(selectedIndex).slider('refresh');
            self.$("#sliderbaserange").val(self.left_rc_index).slider('refresh');

            return change || _.last(self.character.recorded_changes.models);
        },

        update_approval_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            var change = self._update_approval_selected(selectedIndex);

            self._render_viewing(true);

            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != change.id;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self._render_sheet(c, true);
        },

        update_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.idForPickedIndex = selectedIndex;
            self._render_viewing(true);

            var selectedId = this.$("#history-changes-" + selectedIndex).val();
            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != selectedId;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self._render_sheet(c, true);
        },

        _update_transform_description: function(selectedIndex) {
            var self = this;
            var changesToApply = _.chain(self.character.recorded_changes.models).takeRightWhile(function (model, i) {
                return i != selectedIndex;
            }).reverse().value();
            var c = self.character.get_transformed(changesToApply);
            self.transform_description = c.transform_description;
        },

        update_base_selected: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.left_rc_index = selectedIndex;
            self._update_transform_description();
            self._render_viewing(true);
            self._render_sheet();
        },

        _render_viewing: function(enhance) {
            var self = this;
            var sendId = self.idForPickedIndex;
            if (_.isUndefined(sendId)) {
                sendId = self.character.recorded_changes.models.length - 1;
            }
            this.$el.find("#approval-viewing").html(this.approvalSelectedTemplate({
                "character": this.character,
                "logs": self.character.recorded_changes.models,
                "format_entry": this.format_entry,
                "format_approval": this.format_approval,
                idForPickedIndex: sendId,
                left_rc_index: self.left_rc_index,
                approval_index: self.approval_index,
                approvals: self.approvals.models,
                approval: self.approvals.models[self.approval_index]
            }));
            if (enhance) {
                this.$el.find("#approval-viewing").enhanceWithin();
            }
        },

        _render_sheet: function(characterOverride, enhance) {
            var self = this;
            var c = characterOverride || self.character;
            var sortedSkills = c.get_sorted_skills();
            var groupedSkills = c.get_grouped_skills(sortedSkills, 3);
            this.$el.find("#approval-sheet").html(this.sheetTemplate({
                "character": c,
                "skills": sortedSkills,
                "groupedSkills": groupedSkills,
                "transform_description": self.transform_description,
                format_simpletext: this.format_simpletext,
                format_attribute_value: this.format_attribute_value,
                format_attribute_focus: this.format_attribute_focus,
                format_skill: this.format_skill,
                format_specializations: this.format_specializations,
            }));
            if (enhance) {
                this.$el.find("#approval-sheet").enhanceWithin();
            }
        },

        // Renders all of the Category models on the UI
        render: function() {
            var self = this;

            var sendId = self.idForPickedIndex;
            if (_.isUndefined(sendId)) {
                sendId = self.character.recorded_changes.models.length - 1;
            }

            self._update_approval_selected(self.approvals.length);
            self._update_transform_description(self.left_rc_index);

            // Sets the view's template property
            this.template = _.template(character_approval_view_html)({
                    "character": this.character,
                    "logs": this.character.recorded_changes.models,
                    "format_entry": this.format_entry,
                    "format_approval": this.format_approval,
                    idForPickedIndex: sendId,
                    left_rc_index: self.left_rc_index,
                    approval_index: self.approval_index,
                    approvals: self.approvals.models,
                    approval: self.approvals.models[self.approval_index]
                 });

            /*
            _.each(self.approvals.models[self.approval_index], function (approval, i) {
                var headers = ["approved", "change", "approver", "owner"];
                _.each(headers, function (h) {
                    console.log(approval.get(h));
                });
            });
            */
            // Renders the view's template inside of the current listview element
            this.$el.find("#approval-main").html(this.template);

            this._render_viewing();

            this._render_sheet();

            this.$el.enhanceWithin();

            // Maintains chainability
            return this;

        }

    } );

    _.extend(View.prototype, VampirePrintHelper);

    // Returns the View class
    return View;

} );<|endoftext|>


<commit_before>import fs from 'fs-extra'
import path from 'path'

const cwd = process.cwd()

export const copy = (source, target, options, notify) => {
  try {
    const sourceStat = fs.statSync(source)

    if (sourceStat.isFile()) {
      if (options.transform) {
        const transform = options.transform
        const file = fs.readFileSync(source)
        const transformed = transform(file, target)
        const isObject = typeof transformed === 'object'
        const data = isObject && transformed.data || transformed
        const newTarget = isObject && transformed.target || target

        notify('copy', [source, newTarget])

        fs.mkdirsSync(path.dirname(newTarget))
        fs.writeFileSync(newTarget, data)

        notify('copied', [source, newTarget])
      } else {
        notify('copy', [source, target])
        fs.copySync(source, target)

        notify('copied', [source, target])
      }
    } else if (sourceStat.isDirectory()) {
      notify('copy', [source, target])
      fs.ensureDirSync(path.join(target, source.split(path.sep).pop()))

      notify('copied', [source, target])
    }
    return true
  } catch (e) {
    notify('error', e)
    return false
  }
}

export const destroy = (fileordir, notify) => {
  notify('remove', fileordir)
  try {
    fs.removeSync(fileordir)
    return true
  } catch (e) {
    notify('error', e)
    return false
  }
}

export const deleteExtra = (fileordir, options, notify) => {
  if (options.delete) {
    return destroy(fileordir, notify)
  } else {
    notify('no-delete', fileordir)
    return true
  }
}

const getBase = (file, base) => base.filter((base) => file.indexOf(base) !== -1)
    .reduce((hit, base) => hit.length > base.length ? hit : base, '')

export const resolveTarget = (file, target, options) => {
  const from = path.join(cwd, getBase(file, options.base))

  return path.join(target, path.relative(from, file))
}
<commit_msg>undo wrong fix<commit_after>import fs from 'fs-extra'
import path from 'path'

const cwd = process.cwd()

export const copy = (source, target, options, notify) => {
  try {
    const sourceStat = fs.statSync(source)

    if (sourceStat.isFile()) {
      if (options.transform) {
        const transform = options.transform
        const file = fs.readFileSync(source)
        const transformed = transform(file, target)
        const isObject = typeof transformed === 'object'
        const data = isObject && transformed.data || transformed
        const newTarget = isObject && transformed.target || target

        notify('copy', [source, newTarget])

        fs.mkdirsSync(path.dirname(newTarget))
        fs.writeFileSync(newTarget, data)

        notify('copied', [source, newTarget])
      } else {
        notify('copy', [source, target])
        fs.copySync(source, target)

        notify('copied', [source, target])
      }
    } else if (sourceStat.isDirectory()) {
      notify('copy', [source, target])
      fs.ensureDirSync(target)

      notify('copied', [source, target])
    }
    return true
  } catch (e) {
    notify('error', e)
    return false
  }
}

export const destroy = (fileordir, notify) => {
  notify('remove', fileordir)
  try {
    fs.removeSync(fileordir)
    return true
  } catch (e) {
    notify('error', e)
    return false
  }
}

export const deleteExtra = (fileordir, options, notify) => {
  if (options.delete) {
    return destroy(fileordir, notify)
  } else {
    notify('no-delete', fileordir)
    return true
  }
}

const getBase = (file, base) => base.filter((base) => file.indexOf(base) !== -1)
    .reduce((hit, base) => hit.length > base.length ? hit : base, '')

export const resolveTarget = (file, target, options) => {
  const from = path.join(cwd, getBase(file, options.base))

  return path.join(target, path.relative(from, file))
}
<|endoftext|>


<commit_before>const $ = require('jquery');
const { AppSetting } = require('../../core/app_setting');
const { BagItProfile } = require('../../bagit/bagit_profile');
const { BaseController } = require('./base_controller');
const { Constants } = require('../../core/constants');
const { Context } = require('../../core/context');
const Dart = require('../../core');
const { ExportQuestion } = require('../../core/export_question');
const { ExportSettings } = require('../../core/export_settings');
const { RemoteRepository } = require('../../core/remote_repository');
const request = require('request');
const { SettingsExportForm } = require('../forms/settings_export_form');
const { SettingsQuestionsForm } = require('../forms/settings_questions_form');
const { StorageService } = require('../../core/storage_service');
const Templates = require('../common/templates');
const url = require('url');

/**
 * SettingsController imports JSON settings from a URL or from
 * cut-and-pasted text. The settings JSON should be in the format below.
 * Note that each array is optional.
 *
 * @example
 * {
 *   appSettings: [ ... array of AppSetting objects ... ],
 *   bagItProfiles: [ ... array of BagItProfile objects ... ],
 *   remoteRepositories: [ ... array of RemoteRepository objects ... ],
 *   storageServices: [ ... array of StorageService objects ... ],
 * }
 *
 * @see {@link AppSetting}
 * @see {@link BagItProfile}
 * @see {@link RemoteRepository}
 * @see {@link StorageService}
 *
 */
class SettingsController extends BaseController {

    constructor(params) {
        super(params, 'Settings');
        this.questionsForm = null;
    }

    /**
     * Shows the page where a user can import settings from text or a URL.
     *
     */
    import() {
        let html = Templates.settingsImport;
        return this.containerContent(html);
    }

    /**
     * Shows the page where a user can choose which settings to export.
     *
     */
    export() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let form = new SettingsExportForm(settings);
        let data = { form: form };
        let html = Templates.settingsExport(data);
        return this.containerContent(html);
    }

    /**
     * Saves export settings, then redirects to the export settings page.
     *
     */
    saveAndGoToExport() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        this.questionsForm = new SettingsQuestionsForm(settings);
        this.questionsForm.parseQuestionsForExport();
        this.questionsForm.obj.save();
        return this.redirect("Settings", "export", this.params);
    }

    /**
     * Saves export settings, then redirects to the questions page.
     *
     */
    saveAndGoToQuestions() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let itemsForm = new SettingsExportForm(settings);
        itemsForm.parseItemsForExport();
        if (!itemsForm.obj.anythingSelected()) {
            alert(Context.y18n.__("You must select at least one item to export before you can add questions."));
            return this.noContent();
        }
        itemsForm.obj.save();
        return this.redirect("Settings", "showQuestionsForm", this.params);
    }

    /**
     * Shows the form where a user can define setup questions.
     *
     */
    showQuestionsForm() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID);
        this.questionsForm = new SettingsQuestionsForm(settings);
        let html = Templates.settingsQuestions({
            questions: this.questionsForm.getQuestionsAsArray()
        });
        return this.containerContent(html);
    }

    /**
     * Shows the exported settings in JSON format in a modal dialog.
     *
     */
    showExportJson() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let form = null;
        let fromPage = this.params.get("fromPage")
        if (fromPage == "export") {
            form = new SettingsExportForm(settings);
            form.parseItemsForExport();
        } else { // fromPage == "questions"
            form = new SettingsQuestionsForm(settings);
            form.parseQuestionsForExport();
        }
        form.obj.save();
        let title = Context.y18n.__("Exported Settings");
        let body = Templates.settingsExportResult({
            json: JSON.stringify(form.obj, this._jsonFilter, 2)
        });
        return this.modalContent(title, body);
    }

    /**
     * Handler for clicks on the radio button where user specifies
     * that they want to import a BagIt profile from a URL.
     *
     * This shows the URL field and hides the textarea.
     *
     * @private
     */
    _importSourceUrlClick(e) {
        $('#txtJsonContainer').hide();
        $('#txtUrlContainer').show();
    }

    /**
     * Handler for clicks on the radio button where user specifies
     * that they want to import a BagIt profile from cut-and-paste JSON.
     *
     * This shows the textarea and hides the URL field.
     *
     * @private
     */
    _importSourceTextAreaClick(e) {
        $('#txtUrlContainer').hide();
        $('#txtJsonContainer').show();
    }

    /**
     * This attaches event handlers after the page loads.
     *
     * @private
     */
    postRenderCallback(fnName) {
        let controller = this;
        if (fnName == 'import') {
            $('#importSourceUrl').click(() => {
                controller._clearMessage();
                controller._importSourceUrlClick();
            });
            $('#importSourceTextArea').click(() => {
                controller._clearMessage();
                controller._importSourceTextAreaClick();
            });
            $('#btnImport').click(function() {
                controller._clearMessage();
                controller._importSettings();
            });
        } else if (fnName == 'export') {
            $(`input[name="addQuestions"]`).click(() => {
                if ($(`input[name="addQuestions"]`).is(':checked')) {
                    $("#btnNext").text(Context.y18n.__("Add Questions"));
                    $("#btnNext").attr("href", "#Settings/saveAndGoToQuestions");
                } else {
                    $("#btnNext").text(Context.y18n.__("Export"));
                    $("#btnNext").attr("href", "#Settings/showExportJson");
                }
            })
        } else if (fnName == 'showExportJson') {
            $('#btnCopyToClipboard').click(function() { controller._copyToClipboard() });
        } else if (fnName == 'showQuestionsForm') {
            for (let i = 0; i < this.questionsForm.rowCount; i++) {
                controller._attachQuestionCallbacks(i);
            }
            $('#btnAdd').click(() => { controller._addQuestion() });
        }
    }

    /**
     * Adds a new, blank question to the export questions form.
     *
     * @private
     */
    _addQuestion() {
        this.questionsForm.parseQuestionsForExport();
        this.questionsForm.obj.questions.push(new ExportQuestion());
        this.questionsForm.obj.save();
        this.redirect("Settings", "showQuestionsForm", this.params);
    }

    /**
     * Attaches callbacks after the export questions form is rendered.
     *
     * @private
     */
    _attachQuestionCallbacks(rowNumber) {
        let controller = this;
        // When selected object type changes, update the object names list.
        $(`select[data-control-type=object-type][data-row-number=${rowNumber}]`).change(function() {
            let namesList = controller.questionsForm.getNamesList(rowNumber);
            $(`#objId_${rowNumber}`).empty();
            $(`#objId_${rowNumber}`).append(new Option());
            for (let opt of namesList) {
                $(`#objId_${rowNumber}`).append(new Option(opt.name, opt.id));
            }
        });
        // When selected object name changes, updated the fields list.
        $(`select[data-control-type=object-name][data-row-number=${rowNumber}]`).change(function() {
            let fieldsList = controller.questionsForm.getFieldsList(rowNumber);
            $(`#field_${rowNumber}`).empty();
            $(`#field_${rowNumber}`).append(new Option());
            for (let opt of fieldsList) {
                $(`#field_${rowNumber}`).append(new Option(opt.name, opt.id));
            }
        });
    }

    /**
     * This calls the correct function to import DART settings based
     * on the input source (URL or text area).
     *
     * @private
     */
    _importSettings() {
        var importSource = $("input[name='importSource']:checked").val();
        if (importSource == 'URL') {
            this._importSettingsFromUrl($("#txtUrl").val());
        } else if (importSource == 'TextArea') {
            this._importWithErrHandling($("#txtJson").val(), null);
        }
    }

    /**
     * Imports settings from the URL the user specified.
     *
     * @private
     */
    _importSettingsFromUrl(settingsUrl) {
        let controller = this;
        try {
            new url.URL(settingsUrl);
        } catch (ex) {
            controller._showError(Context.y18n.__("Please enter a valid URL."));
            return;
        }
        request(settingsUrl, function (error, response, body) {
            if (error) {
                let msg = Context.y18n.__("Error retrieving profile from %s: %s", settingsUrl, error);
                Context.logger.error(msg);
                controller._showError(msg);
            } else if (response && response.statusCode == 200) {
                // TODO: Make sure response is JSON, not HTML.
                controller._importWithErrHandling(body, settingsUrl);
            } else {
                let statusCode = (response && response.statusCode) || Context.y18n.__('Unknown');
                let msg = Context.y18n.__("Got response %s from %s", statusCode, settingsUrl);
                Context.logger.error(msg);
                controller._showError(msg);
            }
        });
    }

    /**
     * This wraps the import process in a general error handler.
     *
     * @private
     */
    _importWithErrHandling(json, settingsUrl) {
        try {
            this._importSettingsJson(json, settingsUrl);
            this._showSuccess(Context.y18n.__("DART successfully imported the settings."));
            return true;
        } catch (ex) {
            let msg = Context.y18n.__("Error importing settings: %s", ex);
            Context.logger.error(msg);
            Context.logger.error(ex);
            this._showError(msg);
            return false;
        }
    }

    /**
     * This performs the actual import of the settings. It may throw
     * any number of errors, which must be handled by the caller.
     *
     * @private
     */
    _importSettingsJson(json, settingsUrl) {
        let obj;
        try {
            obj = JSON.parse(json);
        } catch (ex) {
            let msg = Context.y18n.__("Error parsing JSON: %s. ", ex.message || ex);
            if (settingsUrl) {
                msg += Context.y18n.__("Be sure the URL returned JSON, not HTML.");
            }
            throw msg;
        }
        this._importSettingsList(obj.appSettings, 'App Setting');
        this._importSettingsList(obj.bagItProfiles, 'BagIt Profile');
        this._importSettingsList(obj.remoteRepositories, 'Remote Repository');
        this._importSettingsList(obj.storageServices, 'Storage Service');
    }

    /**
     * Imports a list of settings from the parsed JSON object.
     *
     * @private
     */
    _importSettingsList(list, objType) {
        if (!Array.isArray(list)) {
            return;
        }
        for (let obj of list) {
            let fullObj = this._inflateObject(obj, objType);
            if (fullObj.validate()) {
                fullObj.save()
            } else {
                controller._showError(Context.y18n.__(
                    "Error importing %s '%s': %s",
                    objType, obj.name, fullObj.errors.join("\n\n")));
            }
        }
    }

    /**
     * Converts a vanilla object to a typed object.
     *
     * @param {Object} obj - An untyped JavaScript object (usually parsed
     * from JSON).
     *
     * @param {string} objType - The type to which to convert the object.
     *
     * @private
     */
    _inflateObject(obj, objType) {
        let fullObj = null;
        switch (objType) {
            case 'App Setting':
              fullObj = AppSetting.inflateFrom(obj);
              break;
            case 'BagIt Profile':
              fullObj = BagItProfile.inflateFrom(obj);
              break;
            case 'Remote Repository':
              fullObj = RemoteRepository.inflateFrom(obj);
              break;
            case 'Storage Service':
              fullObj = StorageService.inflateFrom(obj);
              break;
            break;
        default:
            throw `Unknown setting type: ${objType}`
        }
        return fullObj;
    }

    /**
     * Copies exported settings (JSON) to the system clipboard.
     *
     * @private
     */
    _copyToClipboard() {
        var copyText = document.querySelector("#txtJson");
        copyText.select();
        document.execCommand("copy");
        $("#copied").show();
        $("#copied").fadeOut({duration: 1800});
    }

    /**
     * Displays a success message.
     *
     * @private
     */
    _showSuccess(message) {
        $('#result').hide();
        $('#result').removeClass('text-danger');
        $('#result').addClass('text-success');
        $('#result').text(message);
        $('#result').show();
    }

    /**
     * Displays an error message
     *
     * @private
     */
    _showError(message) {
        $('#result').hide();
        $('#result').addClass('text-danger');
        $('#result').removeClass('text-success');
        $('#result').text(message);
        $('#result').show();
    }

    /**
     * Clears any success/error message from the display.
     *
     * @private
     */
    _clearMessage() {
        $('#result').hide();
        $('#result').text('');
    }
}

module.exports.SettingsController = SettingsController;
<commit_msg>Added TODO items<commit_after>const $ = require('jquery');
const { AppSetting } = require('../../core/app_setting');
const { BagItProfile } = require('../../bagit/bagit_profile');
const { BaseController } = require('./base_controller');
const { Constants } = require('../../core/constants');
const { Context } = require('../../core/context');
const Dart = require('../../core');
const { ExportQuestion } = require('../../core/export_question');
const { ExportSettings } = require('../../core/export_settings');
const { RemoteRepository } = require('../../core/remote_repository');
const request = require('request');
const { SettingsExportForm } = require('../forms/settings_export_form');
const { SettingsQuestionsForm } = require('../forms/settings_questions_form');
const { StorageService } = require('../../core/storage_service');
const Templates = require('../common/templates');
const url = require('url');

// TODO: Hook up question delete button.
// TODO: Add button to clear form.
// TODO: Finish tests for this controller.
// TODO: Finish tests for SettingsQuestionsForm.
// TODO: Copy responses on import.
// TODO: Explicit confirmation on import.

/**
 * SettingsController imports JSON settings from a URL or from
 * cut-and-pasted text. The settings JSON should be in the format below.
 * Note that each array is optional.
 *
 * @example
 * {
 *   appSettings: [ ... array of AppSetting objects ... ],
 *   bagItProfiles: [ ... array of BagItProfile objects ... ],
 *   remoteRepositories: [ ... array of RemoteRepository objects ... ],
 *   storageServices: [ ... array of StorageService objects ... ],
 * }
 *
 * @see {@link AppSetting}
 * @see {@link BagItProfile}
 * @see {@link RemoteRepository}
 * @see {@link StorageService}
 *
 */
class SettingsController extends BaseController {

    constructor(params) {
        super(params, 'Settings');
        this.questionsForm = null;
    }

    /**
     * Shows the page where a user can import settings from text or a URL.
     *
     */
    import() {
        let html = Templates.settingsImport;
        return this.containerContent(html);
    }

    /**
     * Shows the page where a user can choose which settings to export.
     *
     */
    export() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let form = new SettingsExportForm(settings);
        let data = { form: form };
        let html = Templates.settingsExport(data);
        return this.containerContent(html);
    }

    /**
     * Saves export settings, then redirects to the export settings page.
     *
     */
    saveAndGoToExport() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        this.questionsForm = new SettingsQuestionsForm(settings);
        this.questionsForm.parseQuestionsForExport();
        this.questionsForm.obj.save();
        return this.redirect("Settings", "export", this.params);
    }

    /**
     * Saves export settings, then redirects to the questions page.
     *
     */
    saveAndGoToQuestions() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let itemsForm = new SettingsExportForm(settings);
        itemsForm.parseItemsForExport();
        if (!itemsForm.obj.anythingSelected()) {
            alert(Context.y18n.__("You must select at least one item to export before you can add questions."));
            return this.noContent();
        }
        itemsForm.obj.save();
        return this.redirect("Settings", "showQuestionsForm", this.params);
    }

    /**
     * Shows the form where a user can define setup questions.
     *
     */
    showQuestionsForm() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID);
        this.questionsForm = new SettingsQuestionsForm(settings);
        let html = Templates.settingsQuestions({
            questions: this.questionsForm.getQuestionsAsArray()
        });
        return this.containerContent(html);
    }

    /**
     * Shows the exported settings in JSON format in a modal dialog.
     *
     */
    showExportJson() {
        let settings = ExportSettings.find(Constants.EMPTY_UUID) || new ExportSettings();
        let form = null;
        let fromPage = this.params.get("fromPage")
        if (fromPage == "export") {
            form = new SettingsExportForm(settings);
            form.parseItemsForExport();
        } else { // fromPage == "questions"
            form = new SettingsQuestionsForm(settings);
            form.parseQuestionsForExport();
        }
        form.obj.save();
        let title = Context.y18n.__("Exported Settings");
        let body = Templates.settingsExportResult({
            json: JSON.stringify(form.obj, this._jsonFilter, 2)
        });
        return this.modalContent(title, body);
    }

    /**
     * Handler for clicks on the radio button where user specifies
     * that they want to import a BagIt profile from a URL.
     *
     * This shows the URL field and hides the textarea.
     *
     * @private
     */
    _importSourceUrlClick(e) {
        $('#txtJsonContainer').hide();
        $('#txtUrlContainer').show();
    }

    /**
     * Handler for clicks on the radio button where user specifies
     * that they want to import a BagIt profile from cut-and-paste JSON.
     *
     * This shows the textarea and hides the URL field.
     *
     * @private
     */
    _importSourceTextAreaClick(e) {
        $('#txtUrlContainer').hide();
        $('#txtJsonContainer').show();
    }

    /**
     * This attaches event handlers after the page loads.
     *
     * @private
     */
    postRenderCallback(fnName) {
        let controller = this;
        if (fnName == 'import') {
            $('#importSourceUrl').click(() => {
                controller._clearMessage();
                controller._importSourceUrlClick();
            });
            $('#importSourceTextArea').click(() => {
                controller._clearMessage();
                controller._importSourceTextAreaClick();
            });
            $('#btnImport').click(function() {
                controller._clearMessage();
                controller._importSettings();
            });
        } else if (fnName == 'export') {
            $(`input[name="addQuestions"]`).click(() => {
                if ($(`input[name="addQuestions"]`).is(':checked')) {
                    $("#btnNext").text(Context.y18n.__("Add Questions"));
                    $("#btnNext").attr("href", "#Settings/saveAndGoToQuestions");
                } else {
                    $("#btnNext").text(Context.y18n.__("Export"));
                    $("#btnNext").attr("href", "#Settings/showExportJson");
                }
            })
        } else if (fnName == 'showExportJson') {
            $('#btnCopyToClipboard').click(function() { controller._copyToClipboard() });
        } else if (fnName == 'showQuestionsForm') {
            for (let i = 0; i < this.questionsForm.rowCount; i++) {
                controller._attachQuestionCallbacks(i);
            }
            $('#btnAdd').click(() => { controller._addQuestion() });
        }
    }

    /**
     * Adds a new, blank question to the export questions form.
     *
     * @private
     */
    _addQuestion() {
        this.questionsForm.parseQuestionsForExport();
        this.questionsForm.obj.questions.push(new ExportQuestion());
        this.questionsForm.obj.save();
        this.redirect("Settings", "showQuestionsForm", this.params);
    }

    /**
     * Attaches callbacks after the export questions form is rendered.
     *
     * @private
     */
    _attachQuestionCallbacks(rowNumber) {
        let controller = this;
        // When selected object type changes, update the object names list.
        $(`select[data-control-type=object-type][data-row-number=${rowNumber}]`).change(function() {
            let namesList = controller.questionsForm.getNamesList(rowNumber);
            $(`#objId_${rowNumber}`).empty();
            $(`#objId_${rowNumber}`).append(new Option());
            for (let opt of namesList) {
                $(`#objId_${rowNumber}`).append(new Option(opt.name, opt.id));
            }
        });
        // When selected object name changes, updated the fields list.
        $(`select[data-control-type=object-name][data-row-number=${rowNumber}]`).change(function() {
            let fieldsList = controller.questionsForm.getFieldsList(rowNumber);
            $(`#field_${rowNumber}`).empty();
            $(`#field_${rowNumber}`).append(new Option());
            for (let opt of fieldsList) {
                $(`#field_${rowNumber}`).append(new Option(opt.name, opt.id));
            }
        });
    }

    /**
     * This calls the correct function to import DART settings based
     * on the input source (URL or text area).
     *
     * @private
     */
    _importSettings() {
        var importSource = $("input[name='importSource']:checked").val();
        if (importSource == 'URL') {
            this._importSettingsFromUrl($("#txtUrl").val());
        } else if (importSource == 'TextArea') {
            this._importWithErrHandling($("#txtJson").val(), null);
        }
    }

    /**
     * Imports settings from the URL the user specified.
     *
     * @private
     */
    _importSettingsFromUrl(settingsUrl) {
        let controller = this;
        try {
            new url.URL(settingsUrl);
        } catch (ex) {
            controller._showError(Context.y18n.__("Please enter a valid URL."));
            return;
        }
        request(settingsUrl, function (error, response, body) {
            if (error) {
                let msg = Context.y18n.__("Error retrieving profile from %s: %s", settingsUrl, error);
                Context.logger.error(msg);
                controller._showError(msg);
            } else if (response && response.statusCode == 200) {
                // TODO: Make sure response is JSON, not HTML.
                controller._importWithErrHandling(body, settingsUrl);
            } else {
                let statusCode = (response && response.statusCode) || Context.y18n.__('Unknown');
                let msg = Context.y18n.__("Got response %s from %s", statusCode, settingsUrl);
                Context.logger.error(msg);
                controller._showError(msg);
            }
        });
    }

    /**
     * This wraps the import process in a general error handler.
     *
     * @private
     */
    _importWithErrHandling(json, settingsUrl) {
        try {
            this._importSettingsJson(json, settingsUrl);
            this._showSuccess(Context.y18n.__("DART successfully imported the settings."));
            return true;
        } catch (ex) {
            let msg = Context.y18n.__("Error importing settings: %s", ex);
            Context.logger.error(msg);
            Context.logger.error(ex);
            this._showError(msg);
            return false;
        }
    }

    /**
     * This performs the actual import of the settings. It may throw
     * any number of errors, which must be handled by the caller.
     *
     * @private
     */
    _importSettingsJson(json, settingsUrl) {
        let obj;
        try {
            obj = JSON.parse(json);
        } catch (ex) {
            let msg = Context.y18n.__("Error parsing JSON: %s. ", ex.message || ex);
            if (settingsUrl) {
                msg += Context.y18n.__("Be sure the URL returned JSON, not HTML.");
            }
            throw msg;
        }
        this._importSettingsList(obj.appSettings, 'App Setting');
        this._importSettingsList(obj.bagItProfiles, 'BagIt Profile');
        this._importSettingsList(obj.remoteRepositories, 'Remote Repository');
        this._importSettingsList(obj.storageServices, 'Storage Service');
    }

    /**
     * Imports a list of settings from the parsed JSON object.
     *
     * @private
     */
    _importSettingsList(list, objType) {
        if (!Array.isArray(list)) {
            return;
        }
        for (let obj of list) {
            let fullObj = this._inflateObject(obj, objType);
            if (fullObj.validate()) {
                fullObj.save()
            } else {
                controller._showError(Context.y18n.__(
                    "Error importing %s '%s': %s",
                    objType, obj.name, fullObj.errors.join("\n\n")));
            }
        }
    }

    /**
     * Converts a vanilla object to a typed object.
     *
     * @param {Object} obj - An untyped JavaScript object (usually parsed
     * from JSON).
     *
     * @param {string} objType - The type to which to convert the object.
     *
     * @private
     */
    _inflateObject(obj, objType) {
        let fullObj = null;
        switch (objType) {
            case 'App Setting':
              fullObj = AppSetting.inflateFrom(obj);
              break;
            case 'BagIt Profile':
              fullObj = BagItProfile.inflateFrom(obj);
              break;
            case 'Remote Repository':
              fullObj = RemoteRepository.inflateFrom(obj);
              break;
            case 'Storage Service':
              fullObj = StorageService.inflateFrom(obj);
              break;
            break;
        default:
            throw `Unknown setting type: ${objType}`
        }
        return fullObj;
    }

    /**
     * Copies exported settings (JSON) to the system clipboard.
     *
     * @private
     */
    _copyToClipboard() {
        var copyText = document.querySelector("#txtJson");
        copyText.select();
        document.execCommand("copy");
        $("#copied").show();
        $("#copied").fadeOut({duration: 1800});
    }

    /**
     * Displays a success message.
     *
     * @private
     */
    _showSuccess(message) {
        $('#result').hide();
        $('#result').removeClass('text-danger');
        $('#result').addClass('text-success');
        $('#result').text(message);
        $('#result').show();
    }

    /**
     * Displays an error message
     *
     * @private
     */
    _showError(message) {
        $('#result').hide();
        $('#result').addClass('text-danger');
        $('#result').removeClass('text-success');
        $('#result').text(message);
        $('#result').show();
    }

    /**
     * Clears any success/error message from the display.
     *
     * @private
     */
    _clearMessage() {
        $('#result').hide();
        $('#result').text('');
    }
}

module.exports.SettingsController = SettingsController;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { Button, Modal } from 'react-bootstrap';

export class UserCreateModal extends Component {

    constructor(props) {
        super(props);
        this.state = { showModal: false };
    }

  getInitialState() {
    return { showModal: false };
  };

  close = () => {
    this.setState({ showModal: false });
  };

  open = () => {
    this.setState({ showModal: true });
  };

  render() {

    return (

Click to get the full Modal experience!

        <Button
          bsStyle="primary"
          bsSize="large"
          onClick={this.open}
        >
          Launch demo modal
        </Button>

        <Modal show={this.state.showModal} onHide={this.close}>

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

        </Modal>

    );
  }

}

UserCreateModal.propTypes = {

};

export default UserCreateModal;<commit_msg>Modalia<commit_after>import React, { Component, PropTypes } from 'react';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { Button, Modal } from 'react-bootstrap';

export class UserCreateModal extends Component {

    constructor(props) {
        super(props);
        this.state = { showModal: false };
    }

  close = () => {
    this.setState({ showModal: false });
  };

  open = () => {
    this.setState({ showModal: true });
  };

  render() {

    return (

        <Button
          bsStyle="primary"
          onClick={this.open}
        >
          Launch demo modal
        </Button>

        <Modal show={this.state.showModal} onHide={this.close}>

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

        </Modal>

    );
  }

}

UserCreateModal.propTypes = {

};

export default UserCreateModal;<|endoftext|>


<commit_before>'use strict'
/**
 * @property useVal
 * @memberOf Base#
 * @param {*} val
 * Overwrites default set handler and uses val for the property your defining
 * setting to true returns the current instance of Base
 */
exports.useVal = '_useVal'

/**
 * @property noContext
 * @memberOf Base#
 * @param {*} boolean
 * Never create contexts getters for this property
 */
exports.noContext = true
exports.noInstance = true

/**
 * @property ignoreInput
 * @memberOf Base#
 * @param {*} boolean
 * Exclude input from parsevalue
 */
exports.ignoreInput = '_ignoreInput'

/**
 * @property output
 * @memberOf Base#
 * @param {*} val
 * Overwrites input when getting .val
 */
exports.output = true

/**
 * @property Constructor
 * @memberOf Base#
 * Overwrites Constructor
 * @param {*} val
 */
exports.Constructor = true

/**
 * @property key
 * @memberOf Base#
 * @param {String} val - Sets key
 */
exports.key = true

/**
 * @property bind
 * @memberOf Base#
 * @param {*} val - bind this value on emitter, and val getters
 */
exports.bind = true

/**
 * @property Constructor
 * @memberOf Base#
 * Overwrites ChildConstructor
 * @param {*} val
 * if val is string tries to get this[val]
 */
exports._isChild = true
exports.ChildConstructor = exports.Child = function (val, event) {
  var type = typeof val
  if (type === 'string') {
    val = this[val]
  } else if (val && type !== 'function' && val.Constructor) {
    val = val.Constructor
  } else if (type === 'object') {
    if (this.hasOwnProperty('ChildConstructor')) {
      // this is fast but dangerous TODO CLEAN UP
      this.ChildConstructor.prototype.set(val, false)
      return
    }
    val = new this.ChildConstructor(val, event).Constructor
  }
  // if (val.prototype.addAsChild) {
  //   val.prototype.addAsChild(this)
  // }
  if (val) {
    val.prototype._isChild = this // add type for this kind of shit
  }
  this.define({ ChildConstructor: val })
}

/**
 * @property method
 * @memberOf Base#
 * @param {object} val
 *   loop trough val and call methods on base for each key
 *   arrays are parsed for multiple arguments
 *   if you want to pass an array as an argument use [ [ ... ] ]
 * @todo rename this to something better e.g. method
*/
exports.method = function (val) {
  for (let key in val) {
    if (val instanceof Array) {
      this[key].apply(this, val[key])
    } else {
      this[key](val[key])
    }
  }
}

/**
 * @property define
 * @memberOf Base#
 * @param {object} val
 * @todo add util.isArray (faster then instanceof)
 * convenience wrapper for define
*/
exports.define = function (val) {
  if (val instanceof Array) {
    this.define.apply(this, val)
  } else {
    this.define(val)
  }
}

/**
 * @property inject
 * @memberOf Base#
 * @param {object} val
 * convenience wrapper for inject
*/
exports.inject = function (val, event) {
  if (val instanceof Array) {
    if (event) {
      val = val.concat([event])
    }
    this.inject.apply(this, val)
  } else {
    this.inject(val, event)
  }
}

/**
 * @property overwrite
 * @memberOf Base#
 * @param {boolean} val - overwrite current keys and _input of base
 */
exports.overwrite = function (val, event) {
  this.clear(event)
}

/**
 * @property overwrite
 * @memberOf Base#
 * @param {boolean} val - overwrite current keys and _input of base
 */
exports.constructor = function (val, event) {
  this._Constructor = val
  val.prototype = this
}

/**
 * @property origin
 * @memberOf Base#
 * @param {*} val - do a set on the origin
 */
exports.origin = function (val, event) {
  this.origin.set(val, event)
}

/**
 * @property lastStamp
 * @memberOf Base#
 * @param {*} val
 */
exports.lastStamp = true
<commit_msg>added parent to child constructor<commit_after>'use strict'
/**
 * @property useVal
 * @memberOf Base#
 * @param {*} val
 * Overwrites default set handler and uses val for the property your defining
 * setting to true returns the current instance of Base
 */
exports.useVal = '_useVal'

/**
 * @property noContext
 * @memberOf Base#
 * @param {*} boolean
 * Never create contexts getters for this property
 */
exports.noContext = true
exports.noInstance = true

/**
 * @property ignoreInput
 * @memberOf Base#
 * @param {*} boolean
 * Exclude input from parsevalue
 */
exports.ignoreInput = '_ignoreInput'

/**
 * @property output
 * @memberOf Base#
 * @param {*} val
 * Overwrites input when getting .val
 */
exports.output = true

/**
 * @property Constructor
 * @memberOf Base#
 * Overwrites Constructor
 * @param {*} val
 */
exports.Constructor = true

/**
 * @property key
 * @memberOf Base#
 * @param {String} val - Sets key
 */
exports.key = true

/**
 * @property bind
 * @memberOf Base#
 * @param {*} val - bind this value on emitter, and val getters
 */
exports.bind = true

/**
 * @property Constructor
 * @memberOf Base#
 * Overwrites ChildConstructor
 * @param {*} val
 * if val is string tries to get this[val]
 */
exports._isChild = true
exports.ChildConstructor = exports.Child = function (val, event) {
  var type = typeof val
  if (type === 'string') {
    val = this[val]
  } else if (val && type !== 'function' && val.Constructor) {
    val = val.Constructor
  } else if (type === 'object') {
    if (this.hasOwnProperty('ChildConstructor')) {
      // this is fast but dangerous TODO CLEAN UP
      this.ChildConstructor.prototype.set(val, false)
      return
    }
    val = new this.ChildConstructor(val, event, this).Constructor
  }
  // if (val.prototype.addAsChild) {
  //   val.prototype.addAsChild(this)
  // }
  if (val) {
    val.prototype._isChild = this // add type for this kind of shit
  }
  this.define({ ChildConstructor: val })
}

/**
 * @property method
 * @memberOf Base#
 * @param {object} val
 *   loop trough val and call methods on base for each key
 *   arrays are parsed for multiple arguments
 *   if you want to pass an array as an argument use [ [ ... ] ]
 * @todo rename this to something better e.g. method
*/
exports.method = function (val) {
  for (let key in val) {
    if (val instanceof Array) {
      this[key].apply(this, val[key])
    } else {
      this[key](val[key])
    }
  }
}

/**
 * @property define
 * @memberOf Base#
 * @param {object} val
 * @todo add util.isArray (faster then instanceof)
 * convenience wrapper for define
*/
exports.define = function (val) {
  if (val instanceof Array) {
    this.define.apply(this, val)
  } else {
    this.define(val)
  }
}

/**
 * @property inject
 * @memberOf Base#
 * @param {object} val
 * convenience wrapper for inject
*/
exports.inject = function (val, event) {
  if (val instanceof Array) {
    if (event) {
      val = val.concat([event])
    }
    this.inject.apply(this, val)
  } else {
    this.inject(val, event)
  }
}

/**
 * @property overwrite
 * @memberOf Base#
 * @param {boolean} val - overwrite current keys and _input of base
 */
exports.overwrite = function (val, event) {
  this.clear(event)
}

/**
 * @property overwrite
 * @memberOf Base#
 * @param {boolean} val - overwrite current keys and _input of base
 */
exports.constructor = function (val, event) {
  this._Constructor = val
  val.prototype = this
}

/**
 * @property origin
 * @memberOf Base#
 * @param {*} val - do a set on the origin
 */
exports.origin = function (val, event) {
  this.origin.set(val, event)
}

/**
 * @property lastStamp
 * @memberOf Base#
 * @param {*} val
 */
exports.lastStamp = true
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Skywriter.
 *
 * The Initial Developer of the Original Code is
 * Mozilla.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Joe Walker (jwalker@mozilla.com) (original author)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

/**
 * 'bugs' command
 */
var bugsCommandSpec = {
    name: 'bugs',
    returnType: 'html',
    description: 'List the bugs open in Bugzilla',
    exec: function(env, args) {
        var resultPrefix = 'Result for \'' + args.javascript + '\': ';
        try {
            var result = eval(args.javascript);

            if (result === null) {
                return resultPrefix + 'null.';
            }

            if (result === undefined) {
                return resultPrefix + 'undefined.';
            }

            if (typeof result === 'function') {
                return resultPrefix +
                    (result + '').replace(/\n/g, '
').replace(/ /g, '&#160');
            }

            return resultPrefix + result;
        } catch (e) {
            return 'Error: ' + e.message;
        }
    }
};

var gcli = require('gcli/index');

exports.startup = function() {
    gcli.addCommand(bugsCommandSpec);
};

exports.shutdown = function() {
    gcli.removeCommand(bugsCommandSpec);
};

});
<commit_msg>update bugs command<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Skywriter.
 *
 * The Initial Developer of the Original Code is
 * Mozilla.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Joe Walker (jwalker@mozilla.com) (original author)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var gcli = require('gcli/index');

/**
 * 'bugs' command.
 * @see https://wiki.mozilla.org/Bugzilla:REST_API
 * @see https://wiki.mozilla.org/Bugzilla:REST_API:Search
 * @see http://www.bugzilla.org/docs/developer.html
 * @see https://harthur.wordpress.com/2011/03/31/bz-js/
 * @see https://github.com/harthur/bz.js
 */
var bugsCommandSpec = {
    name: 'bugs',
    returnType: 'html',
    description: 'List the bugs open in Bugzilla',
    exec: function(env, args) {
        var promise = gcli.createPromise();
        var url = 'https://api-dev.bugzilla.mozilla.org/0.9/bug' +
            '?short_desc=gcli' +
            '&short_desc_type=allwordssubstr' +
            '&bug_status=UNCONFIRMED' +
            '&bug_status=NEW' +
            '&bug_status=ASSIGNED' +
            '&bug_status=REOPENED' +
            '&component=Developer%20Tools';

        var req = new XMLHttpRequest();
        req.open('GET', url, true);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Content-type', 'application/json');
        req.onreadystatechange = function(event) {
            if (req.readyState == 4) {
                if (req.status >= 300 || req.status < 200) {
                    promise.resolve('Error: ' + JSON.stringify(req));
                    return;
                }

                var json;
                try {
                    json = JSON.parse(req.responseText);
                }
                catch (ex) {
                    promise.resolve('Invalid JSON response: ' + ex + ': ' +
                        req.responseText);
                    return;
                }

                if (json.error) {
                    promise.resolve('Error: ' + json.error.message);
                    return;
                }

                var reply = '
Open devtools bugs with \'gcli\' in the summary ' +
                    '(i.e. this search):' +
                    '
';
                json.bugs.forEach(function(bug) {
                    reply += '
' +
                        '' + bug.id + ': ' +
                        escapeHtml(bug.summary) +
                        '
';
                });
                reply += '
';
                promise.resolve(reply);
            }
        }.bind(this);
        req.send();

        return promise;
    }
};

function escapeHtml(original) {
    return original.replace(/&/g,'&')
        .replace(/</g,'<')
        .replace(/>/g,'>')
        .replace(/"/g,'"')
        .replace(/'/g,''');
};

var gcli = require('gcli/index');

exports.startup = function() {
    gcli.addCommand(bugsCommandSpec);
};

exports.shutdown = function() {
    gcli.removeCommand(bugsCommandSpec);
};

});
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import _ from 'lodash';

const HostsTable = React.createClass({
  propTypes: {
    hosts: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    })),
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
      filteredHosts: this.props.hosts,
      sortDirection: null,
      sortKey: null,
    };
  },

  componentWillReceiveProps(newProps) {
    this.filterHosts(newProps.hosts, this.state.searchTerm);
  },

  filterHosts(allHosts, searchTerm) {
    const hosts = allHosts.filter((h) => {
      let apps = null;
      if (h.apps) {
        apps = h.apps.join(', ');
      } else {
        apps = '';
      }
      return (
        h.name.search(searchTerm) !== -1 ||
        apps.search(searchTerm) !== -1
      );
    });
    this.setState({searchTerm, filteredHosts: hosts});
  },

  changeSort(key) {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection = (this.state.sortDirection === 'asc' ? 'desc' : 'asc');
      this.setState({sortDirection: reverseDirection});
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'});
    }
  },

  sort(hosts, key, direction) {
    switch (direction) {
      case 'asc':
        return _.sortBy(hosts, (e) => e[key]);
      case 'desc':
        return _.sortBy(hosts, (e) => e[key]).reverse();
      default:
        return hosts;
    }
  },

  sortableClasses(key) {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return "sortable-header sorting-up";
      }
      return "sortable-header sorting-down";
    }
    return "sortable-header";
  },

  render() {
    const hosts = this.sort(this.state.filteredHosts, this.state.sortKey, this.state.sortDirection);
    const hostCount = hosts.length;
    const {source} = this.props;

    return (

{hostCount ? `${hostCount} Hosts` : ''}

          <SearchBar onSearch={_.wrap(this.props.hosts, this.filterHosts)} />

                 this.changeSort('name')} className={this.sortableClasses('name')}>Hostname
                Status
                 this.changeSort('cpu')} className={this.sortableClasses('cpu')}>CPU
                 this.changeSort('load')} className={this.sortableClasses('load')}>Load
                Apps

              {
                hosts.map(({name, cpu, load, apps = []}) => {
                  return (

                      <Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>

                      {isNaN(cpu) ? 'N/A' : `${cpu.toFixed(2)}%`}
                      {isNaN(load) ? 'N/A' : `${load.toFixed(2)}`}

                        {apps.map((app, index) => {
                          return (

                              <Link
                                style={{marginLeft: "2px"}}
                                to={{pathname: `/sources/${source.id}/hosts/${name}`, query: {app}}}>
                                {app}
                              </Link>
                              {index === apps.length - 1 ? null : ', '}

                          );
                        })}

                  );
                })
              }

    );
  },
});

const SearchBar = React.createClass({
  propTypes: {
    onSearch: PropTypes.func.isRequired,
  },

  handleChange() {
    this.props.onSearch(this.refs.searchInput.value);
  },

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter Hosts"
          ref="searchInput"
          onChange={this.handleChange}
        />

    );
  },
});

export default HostsTable;
<commit_msg>Hosts Table UI Polish<commit_after>import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import _ from 'lodash';

const HostsTable = React.createClass({
  propTypes: {
    hosts: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    })),
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
      filteredHosts: this.props.hosts,
      sortDirection: null,
      sortKey: null,
    };
  },

  componentWillReceiveProps(newProps) {
    this.filterHosts(newProps.hosts, this.state.searchTerm);
  },

  filterHosts(allHosts, searchTerm) {
    const hosts = allHosts.filter((h) => {
      let apps = null;
      if (h.apps) {
        apps = h.apps.join(', ');
      } else {
        apps = '';
      }
      return (
        h.name.search(searchTerm) !== -1 ||
        apps.search(searchTerm) !== -1
      );
    });
    this.setState({searchTerm, filteredHosts: hosts});
  },

  changeSort(key) {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection = (this.state.sortDirection === 'asc' ? 'desc' : 'asc');
      this.setState({sortDirection: reverseDirection});
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'});
    }
  },

  sort(hosts, key, direction) {
    switch (direction) {
      case 'asc':
        return _.sortBy(hosts, (e) => e[key]);
      case 'desc':
        return _.sortBy(hosts, (e) => e[key]).reverse();
      default:
        return hosts;
    }
  },

  sortableClasses(key) {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return "sortable-header sorting-up";
      }
      return "sortable-header sorting-down";
    }
    return "sortable-header";
  },

  render() {
    const hosts = this.sort(this.state.filteredHosts, this.state.sortKey, this.state.sortDirection);
    const hostCount = hosts.length;
    const {source} = this.props;

    let hostsTitle;
    if (hostCount === 1) {
      hostsTitle = `${hostCount} Host`;
    } else if (hostCount > 1) {
      hostsTitle = `${hostCount} Hosts`;
    } else {
      hostsTitle = `Loading Hosts...`;
    }

    return (

{hostsTitle}

          <SearchBar onSearch={_.wrap(this.props.hosts, this.filterHosts)} />

                 this.changeSort('name')} className={this.sortableClasses('name')}>Hostname
                Status
                 this.changeSort('cpu')} className={this.sortableClasses('cpu')}>CPU
                 this.changeSort('load')} className={this.sortableClasses('load')}>Load
                Apps

              {
                hosts.map(({name, cpu, load, apps = []}) => {
                  return (

                      <Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>

                      {isNaN(cpu) ? 'N/A' : `${cpu.toFixed(2)}%`}
                      {isNaN(load) ? 'N/A' : `${load.toFixed(2)}`}

                        {apps.map((app, index) => {
                          return (

                              <Link
                                style={{marginLeft: "2px"}}
                                to={{pathname: `/sources/${source.id}/hosts/${name}`, query: {app}}}>
                                {app}
                              </Link>
                              {index === apps.length - 1 ? null : ', '}

                          );
                        })}

                  );
                })
              }

    );
  },
});

const SearchBar = React.createClass({
  propTypes: {
    onSearch: PropTypes.func.isRequired,
  },

  handleChange() {
    this.props.onSearch(this.refs.searchInput.value);
  },

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter Hosts"
          ref="searchInput"
          onChange={this.handleChange}
        />

    );
  },
});

export default HostsTable;
<|endoftext|>


<commit_before>
describe('RenderQueue', function() {
	var RenderQueue = $.fullCalendar.RenderQueue;

	it('executes atomic events in sequence', function() {
		var ops = [];
		var q = new RenderQueue();

		q.queue(function() {
			ops.push('fooinit');
		}, 'ent0', 'foo', 'init');

		q.queue(function() {
			ops.push('fooremove');
		}, 'ent0', 'foo', 'add');

		q.queue(function() {
			ops.push('fooadd');
		}, 'ent0', 'foo', 'remove');

		q.queue(function() {
			ops.push('foodestroy');
		}, 'ent0', 'foo', 'destroy');

		expect(ops).toEqual([ 'fooinit', 'fooremove', 'fooadd', 'foodestroy' ]);
	});

	describe('when accumulating', function() {

		describe('using clear action', function() {

			it('destroys add/remove operations in same entity+namespace', function() {
				var ops = [];
				var q = new RenderQueue();
				q.pause();

				q.queue(function() {
					ops.push('fooadd');
				}, 'ent0', 'foo', 'add');

				q.queue(function() {
					ops.push('fooremove');
				}, 'ent0', 'foo', 'remove');

				q.queue(function() {
					ops.push('foodestroy');
				}, 'ent0', 'foo', 'destroy');

				expect(ops).toEqual([]);
				q.resume();
				expect(ops).toEqual([ 'foodestroy' ]);
			});

			it('destroys add/remove operations in same entity+namespace, keeping other entities', function() {
				var ops = [];
				var q = new RenderQueue();
				q.pause();

				q.queue(function() {
					ops.push('foo0add');
				}, 'ent0', 'foo', 'add');

				q.queue(function() {
					ops.push('foo1add');
				}, 'ent1', 'foo', 'add');

				q.queue(function() {
					ops.push('foo0remove');
				}, 'ent0', 'foo', 'remove');

				q.queue(function() {
					ops.push('foo1remove');
				}, 'ent1', 'foo', 'remove');

				q.queue(function() {
					ops.push('foo0destroy');
				}, 'ent0', 'foo', 'destroy');

				expect(ops).toEqual([]);
				q.resume();
				expect(ops).toEqual([ 'foo1add', 'foo1remove', 'foo0destroy' ]);
			});

			it('is cancelled out by an init in same entity+namespace', function() {
				var ops = [];
				var q = new RenderQueue();
				q.pause();

				q.queue(function() {
					ops.push('barinit');
				}, 'ent0', 'bar', 'init');

				q.queue(function() {
					ops.push('fooinit');
				}, 'ent0', 'foo', 'init');

				q.queue(function() {
					ops.push('fooadd');
				}, 'ent0', 'foo', 'add');

				q.queue(function() {
					ops.push('fooadd');
				}, 'ent0', 'foo', 'remove');

				q.queue(function() {
					ops.push('fooadd');
				}, 'ent0', 'foo', 'destroy');

				expect(ops).toEqual([]);
				q.resume();
				expect(ops).toEqual([ 'barinit' ]);
			});
		});
	});

	describe('when namespace has a wait value', function() {

		it('unpauses when done', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'ent0', 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'ent0', 'foo', 'add');

			expect(ops).toEqual([]);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd' ]);
				done();
			}, 200);
		});

		it('restarts timer when new operation happens', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'ent0', 'foo', 'init');

 			setTimeout(function() {
				q.queue(function() {
					ops.push('fooadd');
				}, 'ent0', 'foo', 'add');
			}, 50);

			setTimeout(function() {
				expect(ops).toEqual([]);
			}, 125);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd' ]);
				done();
			}, 175);
		});

		it('causes waiting tasks to delay subsequent non-waiting tasks', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'ent0', 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'ent0', 'foo', 'add');

			expect(ops).toEqual([]);

			q.queue(function() {
				ops.push('barinit');
			}, 'ent0', 'bar', 'init');

			expect(ops).toEqual([]);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd', 'barinit' ]);
				done();
			}, 125);
		});

		it('causes waiting tasks to ignore subsequent waiting tasks\' timeouts', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100,
				bar: 1000
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'ent0', 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'ent0', 'foo', 'add');

			expect(ops).toEqual([]);

			q.queue(function() {
				ops.push('barinit');
			}, 'ent0', 'bar', 'init');

			expect(ops).toEqual([]);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd', 'barinit' ]);
				done();
			}, 125);
		});

		it('resumes non-waiting tasks when unpaused', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.pause();

			q.queue(function() {
				ops.push('barinit');
			}, 'ent0', 'bar', 'init');

			q.queue(function() {
				ops.push('fooinit');
			}, 'ent0', 'foo', 'init');

			q.resume();
			expect(ops).toEqual([ 'barinit' ]);

			setTimeout(function() {
				expect(ops).toEqual([ 'barinit', 'fooinit' ]);
				done();
			}, 200);
		});
	});
});
<commit_msg>revert RenderQueue tests<commit_after>
describe('RenderQueue', function() {
	var RenderQueue = $.fullCalendar.RenderQueue;

	it('executes atomic events in sequence', function() {
		var ops = [];
		var q = new RenderQueue();

		q.queue(function() {
			ops.push('fooinit');
		}, 'foo', 'init');

		q.queue(function() {
			ops.push('fooremove');
		}, 'foo', 'add');

		q.queue(function() {
			ops.push('fooadd');
		}, 'foo', 'remove');

		q.queue(function() {
			ops.push('foodestroy');
		}, 'foo', 'destroy');

		expect(ops).toEqual([ 'fooinit', 'fooremove', 'fooadd', 'foodestroy' ]);
	});

	describe('when accumulating', function() {

		describe('using clear action', function() {

			it('destroys add/remove operations in same namespace', function() {
				var ops = [];
				var q = new RenderQueue();
				q.pause();

				q.queue(function() {
					ops.push('fooadd');
				}, 'foo', 'add');

				q.queue(function() {
					ops.push('fooremove');
				}, 'foo', 'remove');

				q.queue(function() {
					ops.push('foodestroy');
				}, 'foo', 'destroy');

				expect(ops).toEqual([]);
				q.resume();
				expect(ops).toEqual([ 'foodestroy' ]);
			});

			it('is cancelled out by an init in same namespace', function() {
				var ops = [];
				var q = new RenderQueue();
				q.pause();

				q.queue(function() {
					ops.push('barinit');
				}, 'bar', 'init');

				q.queue(function() {
					ops.push('fooinit');
				}, 'foo', 'init');

				q.queue(function() {
					ops.push('fooadd');
				}, 'foo', 'add');

				q.queue(function() {
					ops.push('fooadd');
				}, 'foo', 'remove');

				q.queue(function() {
					ops.push('fooadd');
				}, 'foo', 'destroy');

				expect(ops).toEqual([]);
				q.resume();
				expect(ops).toEqual([ 'barinit' ]);
			});
		});
	});

	describe('when namespace has a wait value', function() {

		it('unpauses when done', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'foo', 'add');

			expect(ops).toEqual([]);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd' ]);
				done();
			}, 200);
		});

		it('restarts timer when new operation happens', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

 			setTimeout(function() {
				q.queue(function() {
					ops.push('fooadd');
				}, 'foo', 'add');
			}, 50);

			setTimeout(function() {
				expect(ops).toEqual([]);
			}, 125);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd' ]);
				done();
			}, 175);
		});

		it('synchronously executes queue when sync non-namespace operation happens', function() {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'foo', 'add');

			expect(ops).toEqual([]);

			q.queue(function() {
				ops.push('barinit');
			}, 'bar', 'init');

			expect(ops).toEqual([ 'fooinit', 'fooadd', 'barinit' ]);
		});

		it('synchronously executes queue when async non-namespace operation happens', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100,
				bar: 100
			});

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

			q.queue(function() {
				ops.push('fooadd');
			}, 'foo', 'add');

			expect(ops).toEqual([]);

			q.queue(function() {
				ops.push('barinit');
			}, 'bar', 'init');

			expect(ops).toEqual([ 'fooinit', 'fooadd' ]);

			setTimeout(function() {
				expect(ops).toEqual([ 'fooinit', 'fooadd', 'barinit' ]);
				done();
			}, 200);
		});

		it('resumes non-waiting tasks when unpaused', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.pause();

			q.queue(function() {
				ops.push('barinit');
			}, 'bar', 'init');

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

			q.resume();
			expect(ops).toEqual([ 'barinit' ]);

			setTimeout(function() {
				expect(ops).toEqual([ 'barinit', 'fooinit' ]);
				done();
			}, 200);
		});

		it('paused+queued tasks from a previous namespace wait resume immediately', function(done) {
			var ops = [];
			var q = new RenderQueue({
				foo: 100
			});

			q.pause();

			q.queue(function() {
				ops.push('foodestroy');
			}, 'foo', 'destroy');

			q.queue(function() {
				ops.push('bardestroy');
			}, 'bar', 'destroy');

			expect(ops).toEqual([]);

			q.queue(function() {
				ops.push('barinit');
			}, 'bar', 'init');

			q.queue(function() {
				ops.push('fooinit');
			}, 'foo', 'init');

			expect(ops).toEqual([]);

			q.resume();
			expect(ops).toEqual([ 'foodestroy', 'bardestroy', 'barinit' ]);

			setTimeout(function() {
				expect(ops).toEqual([ 'foodestroy', 'bardestroy', 'barinit', 'fooinit' ]);
				done();
			}, 200);
		});
	});
});
<|endoftext|>