<commit_before>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

/**
 * Module: Editor
 */
define( [ "util/lang", "util/xhr",
          "./base-editor", "./trackevent-editor" ],
  function( LangUtils, XHRUtils,
            BaseEditor, TrackEventEditor ) {

  var __editors = {};

  function DeferredLayout( src ) {

    this.load = function( baseDir, readyCallback ) {
      baseDir = baseDir || "";
      if ( src.indexOf( "{{baseDir}}" ) > -1 ) {
        src = src.replace( "{{baseDir}}", baseDir );
      }

      XHRUtils.get( src, function( e ) {
        if ( e.target.readyState === 4 ){
          readyCallback( e.target.responseText );
        }
      }, "text/plain" );
    };
 }

  /**
   * Namespace: Editor
   */
  var Editor = {

    BaseEditor: BaseEditor,
    TrackEventEditor: TrackEventEditor,

    /**
     * Function: register
     *
     * Registers an editor in the system.
     *
     * @param {String} name: Name of the editor
     * @param {String} layoutSrc: String representing the basic HTML layout of the editor. May be prepended with "load!" to signify that load must be done after butter is initialized.
     * @param {Function} ctor: Constructor to be run when the Editor is being created
     */
    register: function( name, layoutSrc, ctor, persist ) {
      __editors[ name ] = {
        create: ctor,
        persist: !!persist,
        layout: layoutSrc || "",
        deferredLayouts: []
      };

      function processLayoutEntry( src ) {
        var deferredLayout;
        if ( src.indexOf( "load!" ) === 0 ) {
           deferredLayout = new DeferredLayout( src.substring( 5 ) );
           __editors[ name ].deferredLayouts.push( deferredLayout );
           return true;
        }
        return false;
      }

      if ( layoutSrc ) {
        if ( Array.isArray( layoutSrc ) ) {
          layoutSrc.forEach( processLayoutEntry );
        }
        else {
          if ( processLayoutEntry( layoutSrc ) ) {
            __editors[ name ].layout = "";
          }
        }
      }
    },

    /**
     * Function: initialize
     *
     * Initializes the Editor module.
     *
     * For layouts that were specified as `load!<url>`, replace the url with actual layout content by loading
     * it through XHR. This is useful for editors specified in Butter config files, since using `Butter.Editor`
     * outside of the core will not guarantee that {{baseDir}} properly exists until #1245 has landed:
     *
     * https://webmademovies.lighthouseapp.com/projects/65733/tickets/1245-remove-instances-have-butter-become-a-singleton
     *
     * @param {Function} readyCallback: After all layouts have been loaded, call this function.
     * @param {String} baseDir: The baseDir found in Butter's config which is used to replace {{baseDir}} in urls.
     */
    initialize: function( readyCallback, baseDir ) {
      var editorName,
          editorsLoaded = 0,
          editorsToLoad = [];

      for ( editorName in __editors ) {
        if ( __editors.hasOwnProperty( editorName ) && __editors[ editorName ].deferredLayouts.length > 0 ) {
          editorsToLoad.push( __editors[ editorName ] );
        }
      }

      editorsToLoad.forEach( function( editor ) {
        var finishedLayouts = 0;
        editor.deferredLayouts.forEach( function( deferredLayout ) {
          deferredLayout.load( baseDir, function( layoutData ) {
            ++finishedLayouts;
            editor.layout += layoutData;
            if ( finishedLayouts === editor.deferredLayouts.length ) {
              editor.deferredLayouts = null;
              ++editorsLoaded;
              if ( editorsLoaded === editorsToLoad.length ) {
                readyCallback();
              }
            }
          });
        });
      });
    },

    /**
     * Function: create
     *
     * Creates an editor
     *
     * @param {String} editorName: Name of the editor to create
     * @param {Butter} butter: An instance of Butter
     */
    create: function( editorName, butter ) {
      var description = __editors[ editorName ],
          completeLayout,
          compiledLayout;

      if ( !description ) {
        throw "Editor \"" + editorName + "\" does not exist.";
      }

      if ( description.layout ) {
        // Collect the element labeled with the 'butter-editor' class to avoid other elements (such as comments)
        // which may exist in the layout.
        compiledLayout = LangUtils.domFragment( description.layout );

        // Expose the full compiledLayout to the editor for later use.
        completeLayout = compiledLayout;

        // If domFragment returned a DOMFragment (not an actual element) try to get the proper element out of it
        if ( !compiledLayout.classList ) {
          compiledLayout = compiledLayout.querySelector( ".butter-editor" );
        }

        if ( !compiledLayout ) {
          throw "Editor layout not formatted properly.";
        }
      }

      return new description.create( compiledLayout, butter, completeLayout );
    },

    /**
     * Function: isRegistered
     *
     * Reports the existence of an editor given a name
     *
     * @param {String} name: Name of the editor of which existence will be verified
     */
    isRegistered: function( name ) {
      return !!__editors[ name ];
    },

    isPersistent: function( editorName ) {
      return __editors[ editorName ].persist;
    }

  };

  return Editor;

});
<commit_msg>Bug #3441 - Convert editor/editor to use xhr2<commit_after>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

/**
 * Module: Editor
 */
define( [ "util/lang", "util/xhr2",
          "./base-editor", "./trackevent-editor" ],
  function( LangUtils, xhr,
            BaseEditor, TrackEventEditor ) {

  var __editors = {};

  function DeferredLayout( src ) {

    this.load = function( baseDir, readyCallback ) {
      baseDir = baseDir || "";
      if ( src.indexOf( "{{baseDir}}" ) > -1 ) {
        src = src.replace( "{{baseDir}}", baseDir );
      }

      xhr.get( src, readyCallback );
    };
 }

  /**
   * Namespace: Editor
   */
  var Editor = {

    BaseEditor: BaseEditor,
    TrackEventEditor: TrackEventEditor,

    /**
     * Function: register
     *
     * Registers an editor in the system.
     *
     * @param {String} name: Name of the editor
     * @param {String} layoutSrc: String representing the basic HTML layout of the editor. May be prepended with "load!" to signify that load must be done after butter is initialized.
     * @param {Function} ctor: Constructor to be run when the Editor is being created
     */
    register: function( name, layoutSrc, ctor, persist ) {
      __editors[ name ] = {
        create: ctor,
        persist: !!persist,
        layout: layoutSrc || "",
        deferredLayouts: []
      };

      function processLayoutEntry( src ) {
        var deferredLayout;
        if ( src.indexOf( "load!" ) === 0 ) {
           deferredLayout = new DeferredLayout( src.substring( 5 ) );
           __editors[ name ].deferredLayouts.push( deferredLayout );
           return true;
        }
        return false;
      }

      if ( layoutSrc ) {
        if ( Array.isArray( layoutSrc ) ) {
          layoutSrc.forEach( processLayoutEntry );
        }
        else {
          if ( processLayoutEntry( layoutSrc ) ) {
            __editors[ name ].layout = "";
          }
        }
      }
    },

    /**
     * Function: initialize
     *
     * Initializes the Editor module.
     *
     * For layouts that were specified as `load!<url>`, replace the url with actual layout content by loading
     * it through XHR. This is useful for editors specified in Butter config files, since using `Butter.Editor`
     * outside of the core will not guarantee that {{baseDir}} properly exists until #1245 has landed:
     *
     * https://webmademovies.lighthouseapp.com/projects/65733/tickets/1245-remove-instances-have-butter-become-a-singleton
     *
     * @param {Function} readyCallback: After all layouts have been loaded, call this function.
     * @param {String} baseDir: The baseDir found in Butter's config which is used to replace {{baseDir}} in urls.
     */
    initialize: function( readyCallback, baseDir ) {
      var editorName,
          editorsLoaded = 0,
          editorsToLoad = [];

      for ( editorName in __editors ) {
        if ( __editors.hasOwnProperty( editorName ) && __editors[ editorName ].deferredLayouts.length > 0 ) {
          editorsToLoad.push( __editors[ editorName ] );
        }
      }

      editorsToLoad.forEach( function( editor ) {
        var finishedLayouts = 0;
        editor.deferredLayouts.forEach( function( deferredLayout ) {
          deferredLayout.load( baseDir, function( layoutData ) {
            ++finishedLayouts;
            editor.layout += layoutData;
            if ( finishedLayouts === editor.deferredLayouts.length ) {
              editor.deferredLayouts = null;
              ++editorsLoaded;
              if ( editorsLoaded === editorsToLoad.length ) {
                readyCallback();
              }
            }
          });
        });
      });
    },

    /**
     * Function: create
     *
     * Creates an editor
     *
     * @param {String} editorName: Name of the editor to create
     * @param {Butter} butter: An instance of Butter
     */
    create: function( editorName, butter ) {
      var description = __editors[ editorName ],
          completeLayout,
          compiledLayout;

      if ( !description ) {
        throw "Editor \"" + editorName + "\" does not exist.";
      }

      if ( description.layout ) {
        // Collect the element labeled with the 'butter-editor' class to avoid other elements (such as comments)
        // which may exist in the layout.
        compiledLayout = LangUtils.domFragment( description.layout );

        // Expose the full compiledLayout to the editor for later use.
        completeLayout = compiledLayout;

        // If domFragment returned a DOMFragment (not an actual element) try to get the proper element out of it
        if ( !compiledLayout.classList ) {
          compiledLayout = compiledLayout.querySelector( ".butter-editor" );
        }

        if ( !compiledLayout ) {
          throw "Editor layout not formatted properly.";
        }
      }

      return new description.create( compiledLayout, butter, completeLayout );
    },

    /**
     * Function: isRegistered
     *
     * Reports the existence of an editor given a name
     *
     * @param {String} name: Name of the editor of which existence will be verified
     */
    isRegistered: function( name ) {
      return !!__editors[ name ];
    },

    isPersistent: function( editorName ) {
      return __editors[ editorName ].persist;
    }

  };

  return Editor;

});
<|endoftext|>


<commit_before>'use strict';

function RTE(el)
{
    const tags =
    {
        'mode' : function (editor, sel)
        {
            editor.setAttribute('data-rte-mode', editor.getAttribute('data-rte-mode') === 'src' ? 'rte' : 'src');
        },
        'undo' : function (editor, sel)
        {
            cmd('undo', null);
        },
        'redo' : function (editor, sel)
        {
            cmd('redo', null);
        },
        'remove' : function (editor, sel)
        {
            cmd('removeFormat', null);
        },
        'b' : function (editor, sel)
        {
            cmd('bold', null);
        },
        'i' : function (editor, sel)
        {
            cmd('italic', null);
        },
        'u' : function (editor, sel)
        {
            insertHtml('u', sel);
        },
        'small' : function (editor, sel)
        {
            insertHtml('small', sel);
        },
        's' : function (editor, sel)
        {
            insertHtml('s', sel);
        },
        'sup' : function (editor, sel)
        {
            insertHtml('sup', sel);
        },
        'sub' : function (editor, sel)
        {
            insertHtml('sub', sel);
        },
        'link' : function (editor, sel)
        {
            if (value = prompt('URL', 'http://')) {
                cmd('createLink', value);
            }
        },
        'unlink' : function (editor, sel)
        {
            cmd('unlink', null);
        },
        'img' : function (editor, sel)
        {
            if (value = prompt('URL', 'http://')) {
                cmd('insertImage', value);
            }
        },
        'h1' : function (editor, sel)
        {
            cmd('formatBlock', '<h1>');
        },
        'h2' : function (editor, sel)
        {
            cmd('formatBlock', '<h2>');
        },
        'h3' : function (editor, sel)
        {
            cmd('formatBlock', '<h3>');
        },
        'h4' : function (editor, sel)
        {
            cmd('formatBlock', '<h4>');
        },
        'h5' : function (editor, sel)
        {
            cmd('formatBlock', '<h5>');
        },
        'h6' : function (editor, sel)
        {
            cmd('formatBlock', '<h6>');
        },
        'p' : function (editor, sel)
        {
            cmd('insertParagraph', null);
        },
        'blockquote' : function (editor, sel)
        {
            cmd('formatBlock', '<blockquote>');
        },
        'ol' : function (editor, sel)
        {
            cmd('insertOrderedList', null);
        },
        'ul' : function (editor, sel)
        {
            cmd('insertUnorderedList', null);
        }
    };

    const allowed = ['b', 'i', 'u', 'strong', 'em', 'small', 's', 'sup', 'sub', 'a', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'ol', 'ul', 'li', 'br'];

    function init(el)
    {
        let editor = el;

        if (el.nodeName.toLowerCase() === 'textarea') {
            editor = document.createElement('div');
            editor.setAttribute('contenteditable', true);
            editor.setAttribute('data-rte-mode', 'rte');
            editor.innerHTML = decode(el.innerHTML);
            el.parentNode.appendChild(editor);
            el.setAttribute('hidden', true);

            const f =  el.getAttribute('form'),
                form = f ? document.getElementById(f) : el.closest('form');

            form.addEventListener('submit', function()
            {
                el.innerHTML = trim(strip(decode(editor.innerHTML)));
            });

            toolbar(editor);
        } else {
            editor.addEventListener('focus', function()
            {
                toolbar(editor);
            });
        }

        editor.addEventListener('change', function()
        {
            let html = strip(decode(editor.innerHTML));
            editor.innerHTML = editor.getAttribute('data-rte-mode') === 'src' ? encode(html) : html;
        });
    }

    function toolbar(editor)
    {
        if (editor._initialized) {
            return;
        }

        const toolbar = document.createElement('div');
        toolbar.setAttribute('data-rte-toolbar', true);

        for (let key in tags) {
            if (!tags.hasOwnProperty(key)) {
                continue;
            }

            const button = document.createElement('button');
            button.setAttribute('type', 'button');
            button.setAttribute('data-rte-cmd', key);
            button.textContent = key;
            button.addEventListener('click', function()
            {
                const sel = window.getSelection(),
                    callback = tags[this.getAttribute('data-rte-cmd')] || null;

                // Selection outside element or invalid key
                if (!sel.containsNode(editor, true) || !callback) {
                    return false;
                }

                // Callback
                callback(editor, sel);
                editor.dispatchEvent(new Event('change'));

                return false;
            });

            toolbar.appendChild(button);
        }

        editor.parentNode.insertBefore(toolbar, editor);
        editor._initialized = true;
    }

    function cmd(command, value)
    {
        try {
            document.execCommand(command, false, value);
        } catch (e) {
            console.log(e);
        }
    }

    function insertHtml(tag, sel)
    {
        const html = sel.toString();

        if (tag && html.length > 0) {
            cmd('insertHTML', '<' + tag + '>' + html + '</' + tag + '>');
        }
    }

    function trim(html)
    {
        return html ? html.trim().replace(/\s/g, ' ').replace(/^((<|<)br\s*\/*(>|>))+/gi, ' ').replace(/((<|<)br\s*\/*(>|>))+$/gi, ' ').trim() : '';
    }

    function encode(html)
    {
        return html ? html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''') : '';
    }

    function decode(html)
    {
        return html ? html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'") : '';
    }

    function strip(html)
    {
        if (!html) {
            return '';
        }

        return html.replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, function($0, $1)
        {
            return allowed.indexOf($1.toLowerCase()) > -1 ? $0 : '';
        });
    }

    init(el);
}
<commit_msg>Use sub-/superscript<commit_after>'use strict';

function RTE(el)
{
    const tags =
    {
        'mode' : function (editor, sel)
        {
            editor.setAttribute('data-rte-mode', editor.getAttribute('data-rte-mode') === 'src' ? 'rte' : 'src');
        },
        'undo' : function (editor, sel)
        {
            cmd('undo', null);
        },
        'redo' : function (editor, sel)
        {
            cmd('redo', null);
        },
        'remove' : function (editor, sel)
        {
            cmd('removeformat', null);
        },
        'b' : function (editor, sel)
        {
            cmd('bold', null);
        },
        'i' : function (editor, sel)
        {
            cmd('italic', null);
        },
        'u' : function (editor, sel)
        {
            insertHtml('u', sel);
        },
        'small' : function (editor, sel)
        {
            insertHtml('small', sel);
        },
        's' : function (editor, sel)
        {
            insertHtml('s', sel);
        },
        'sup' : function (editor, sel)
        {
            cmd('superscript', null);
        },
        'sub' : function (editor, sel)
        {
            cmd('subscript', null);
        },
        'link' : function (editor, sel)
        {
            if (value = prompt('URL', 'http://')) {
                cmd('createlink', value);
            }
        },
        'unlink' : function (editor, sel)
        {
            cmd('unlink', null);
        },
        'img' : function (editor, sel)
        {
            if (value = prompt('URL', 'http://')) {
                cmd('insertimage', value);
            }
        },
        'h1' : function (editor, sel)
        {
            cmd('formatblock', '<h1>');
        },
        'h2' : function (editor, sel)
        {
            cmd('formatblock', '<h2>');
        },
        'h3' : function (editor, sel)
        {
            cmd('formatblock', '<h3>');
        },
        'h4' : function (editor, sel)
        {
            cmd('formatblock', '<h4>');
        },
        'h5' : function (editor, sel)
        {
            cmd('formatblock', '<h5>');
        },
        'h6' : function (editor, sel)
        {
            cmd('formatblock', '<h6>');
        },
        'p' : function (editor, sel)
        {
            cmd('insertparagraph', null);
        },
        'blockquote' : function (editor, sel)
        {
            cmd('formatblock', '<blockquote>');
        },
        'ol' : function (editor, sel)
        {
            cmd('insertorderedlist', null);
        },
        'ul' : function (editor, sel)
        {
            cmd('insertunorderedlist', null);
        }
    };

    const allowed = ['b', 'i', 'u', 'strong', 'em', 'small', 's', 'sup', 'sub', 'a', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'ol', 'ul', 'li', 'br'];

    function init(el)
    {
        let editor = el;

        if (el.nodeName.toLowerCase() === 'textarea') {
            editor = document.createElement('div');
            editor.setAttribute('contenteditable', true);
            editor.setAttribute('data-rte-mode', 'rte');
            editor.innerHTML = decode(el.innerHTML);
            el.parentNode.appendChild(editor);
            el.setAttribute('hidden', true);

            const f =  el.getAttribute('form'),
                form = f ? document.getElementById(f) : el.closest('form');

            form.addEventListener('submit', function()
            {
                el.innerHTML = trim(strip(decode(editor.innerHTML)));
            });

            toolbar(editor);
        } else {
            editor.addEventListener('focus', function()
            {
                toolbar(editor);
            });
        }

        editor.addEventListener('change', function()
        {
            let html = strip(decode(editor.innerHTML));
            editor.innerHTML = editor.getAttribute('data-rte-mode') === 'src' ? encode(html) : html;
        });
    }

    function toolbar(editor)
    {
        if (editor._initialized) {
            return;
        }

        const toolbar = document.createElement('div');
        toolbar.setAttribute('data-rte-toolbar', true);

        for (let key in tags) {
            if (!tags.hasOwnProperty(key)) {
                continue;
            }

            const button = document.createElement('button');
            button.setAttribute('type', 'button');
            button.setAttribute('data-rte-cmd', key);
            button.textContent = key;
            button.addEventListener('click', function()
            {
                const sel = window.getSelection(),
                    callback = tags[this.getAttribute('data-rte-cmd')] || null;

                // Selection outside element or invalid key
                if (!sel.containsNode(editor, true) || !callback) {
                    return false;
                }

                // Callback
                callback(editor, sel);
                editor.dispatchEvent(new Event('change'));

                return false;
            });

            toolbar.appendChild(button);
        }

        editor.parentNode.insertBefore(toolbar, editor);
        editor._initialized = true;
    }

    function cmd(command, value)
    {
        try {
            document.execCommand(command, false, value);
        } catch (e) {
            console.log(e);
        }
    }

    function insertHtml(tag, sel)
    {
        const html = sel.toString();

        if (tag && html.length > 0) {
            cmd('insertHTML', '<' + tag + '>' + html + '</' + tag + '>');
        }
    }

    function trim(html)
    {
        return html ? html.trim().replace(/\s/g, ' ').replace(/^((<|<)br\s*\/*(>|>))+/gi, ' ').replace(/((<|<)br\s*\/*(>|>))+$/gi, ' ').trim() : '';
    }

    function encode(html)
    {
        return html ? html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''') : '';
    }

    function decode(html)
    {
        return html ? html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'") : '';
    }

    function strip(html)
    {
        if (!html) {
            return '';
        }

        return html.replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, function($0, $1)
        {
            return allowed.indexOf($1.toLowerCase()) > -1 ? $0 : '';
        });
    }

    init(el);
}
<|endoftext|>


<commit_before>define(['underscore', 'models/base', 'collections/instances'], function(_, Base, Instances) {
    var Identity = Base.extend({
        defaults: { 'model_name': 'identity' },
        initialize: function(attributes, options) {
            attributes.quota.mem *= 1024;
        },
        parse: function(response) {
            var attributes = response;

            attributes.id = response.id;
            attributes.provider_id = response.provider_id;
            //attributes.credentials = response.credentials;
            attributes.quota = response.quota;
            attributes.quota.mem = response.quota.mem * 1024;
            attributes.quota.cpu = response.quota.cpu;
            attributes.quota.disk = response.quota.disk;
            attributes.quota.disk_count = response.quota.disk_count;

            return attributes;
        },
        has_allocation: function() {
            return ( typeof this.attributes.quota.allocation != 'undefined')
        },
        url: function() {
            var creds = Atmo.get_credentials();
            return url = this.urlRoot
                + '/provider/' + creds.provider_id
                + '/' + this.defaults.model_name + '/';
        },
        /*
         * Overriding get for caching collections
         */
        get: function(attr) {
            if (typeof this[attr] == 'function')
                return this[attr]();
            return Backbone.Model.prototype.get.call(this, attr);
        },
        instances: function() {
            var instances = this.get('_instances');
            if (!instances) {
                instances = new Instances(null, {
                    provider_id: this.get('provider_id'),
                    identity_id: this.id
                });
                this.set('_instances', instances);
            }
            return instances;
        }
    });

    _.extend(Identity.defaults, Base.defaults);

    return Identity;
});
<commit_msg>Identity.volumes() now returns an identity's collection of volumes<commit_after>define(['underscore', 'models/base', 'collections/instances', 'collections/volumes'], function(_, Base, Instances, Volumes) {
    var Identity = Base.extend({
        defaults: { 'model_name': 'identity' },
        initialize: function(attributes, options) {
            attributes.quota.mem *= 1024;
        },
        parse: function(response) {
            var attributes = response;

            attributes.id = response.id;
            attributes.provider_id = response.provider_id;
            //attributes.credentials = response.credentials;
            attributes.quota = response.quota;
            attributes.quota.mem = response.quota.mem * 1024;
            attributes.quota.cpu = response.quota.cpu;
            attributes.quota.disk = response.quota.disk;
            attributes.quota.disk_count = response.quota.disk_count;

            return attributes;
        },
        has_allocation: function() {
            return ( typeof this.attributes.quota.allocation != 'undefined')
        },
        url: function() {
            var creds = Atmo.get_credentials();
            return url = this.urlRoot
                + '/provider/' + creds.provider_id
                + '/' + this.defaults.model_name + '/';
        },
        /*
         * Overriding get for caching collections
         */
        get: function(attr) {
            if (typeof this[attr] == 'function')
                return this[attr]();
            return Backbone.Model.prototype.get.call(this, attr);
        },
        get_collection: function(cls, key) {
            var collection = this.get(key);
            if (!collection) {
                collection = new cls(null, {
                    provider_id: this.get('provider_id'),
                    identity_id: this.id
                });
                this.set(key, collection);
            }
            return collection;
        },
        instances: function() {
            return this.get_collection(Instances, '_instances');
        },
        volumes: function() {
            return this.get_collection(Volumes, '_volumes');
        }
    });

    _.extend(Identity.defaults, Base.defaults);

    return Identity;
});
<|endoftext|>


<commit_before>'use strict';

import {Pipe} from 'angular2/core';
import {isString, stringify, isBlank} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {JsonPointer} from './JsonPointer';
import marked from 'marked';

marked.setOptions({
  renderer: new marked.Renderer(),
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  smartLists: true,
  smartypants: false
});

class InvalidPipeArgumentException extends BaseException {
  constructor(type, value) {
    super(`Invalid argument '${value}' for pipe '${stringify(type)}'`);
  }
}

@Pipe({ name: 'keys' })
export class KeysPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (typeof value !== 'object') {
      throw new InvalidPipeArgumentException(ValuesPipe, value);
    }
    return Object.keys(value);
  }
}

@Pipe({ name: 'values' })
export class ValuesPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (typeof value !== 'object') {
      throw new InvalidPipeArgumentException(ValuesPipe, value);
    }
    return Object.keys(value).map(key => value[key]);
  }
}

@Pipe({ name: 'jsonPointerEscape' })
export class JsonPointerEscapePipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value);
    }
    return JsonPointer.escape(value);
  }
}

@Pipe({ name: 'marked' })
export class MarkedPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value);
    }
    return `<span class="redoc-markdown-block">${marked(value)}</span>`;
  }
}
<commit_msg>Add prism.js pipe<commit_after>'use strict';

import {Pipe} from 'angular2/core';
import {isString, stringify, isBlank} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {JsonPointer} from './JsonPointer';
import marked from 'marked';
import Prism from 'prismjs';
import 'prismjs/components/prism-actionscript.js';
import 'prismjs/components/prism-c.js';
import 'prismjs/components/prism-cpp.js';
import 'prismjs/components/prism-csharp.js';
import 'prismjs/components/prism-php.js';
import 'prismjs/components/prism-coffeescript.js';
import 'prismjs/components/prism-go.js';
import 'prismjs/components/prism-haskell.js';
import 'prismjs/components/prism-scala.js';
import 'prismjs/components/prism-java.js';
import 'prismjs/components/prism-lua.js';
import 'prismjs/components/prism-matlab.js';
import 'prismjs/components/prism-objectivec.js';
import 'prismjs/components/prism-perl.js';
import 'prismjs/components/prism-python.js';
import 'prismjs/components/prism-r.js';
import 'prismjs/components/prism-ruby.js';

import 'prismjs/components/prism-bash.js';
import 'prismjs/components/prism-swift.js';
import 'prismjs/components/prism-vim.js';

import 'prismjs/themes/prism-dark.css!css';

marked.setOptions({
  renderer: new marked.Renderer(),
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  smartLists: true,
  smartypants: false
});

class InvalidPipeArgumentException extends BaseException {
  constructor(type, value) {
    super(`Invalid argument '${value}' for pipe '${stringify(type)}'`);
  }
}

@Pipe({ name: 'keys' })
export class KeysPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (typeof value !== 'object') {
      throw new InvalidPipeArgumentException(ValuesPipe, value);
    }
    return Object.keys(value);
  }
}

@Pipe({ name: 'values' })
export class ValuesPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (typeof value !== 'object') {
      throw new InvalidPipeArgumentException(ValuesPipe, value);
    }
    return Object.keys(value).map(key => value[key]);
  }
}

@Pipe({ name: 'jsonPointerEscape' })
export class JsonPointerEscapePipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value);
    }
    return JsonPointer.escape(value);
  }
}

@Pipe({ name: 'marked' })
export class MarkedPipe {
  transform(value) {
    if (isBlank(value)) return value;
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value);
    }
    return `<span class="redoc-markdown-block">${marked(value)}</span>`;
  }
}

const langMap = {
  'c++': 'cpp',
  'c#': 'csharp',
  'objective-c': 'objectivec',
  'shell': 'bash',
  'viml': 'vim'
};

@Pipe({ name: 'prism' })
export class PrismPipe {
  transform(value, args) {
    if (isBlank(args) || args.length === 0) {
      throw new BaseException('Prism pipe requires one argument');
    }
    if (isBlank(value)) return value;
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value);
    }
    let lang = args[0].toString().trim().toLowerCase();
    if (langMap[lang]) lang = langMap[lang];

    let grammar = Prism.languages[lang];
    //fallback to clike
    if (!grammar) grammar = Prism.languages.clike;
    return Prism.highlight(value, grammar);
  }
}
<|endoftext|>


<commit_before>'use strict';

const isObject = require('./typeof').isObject;
const isUndefined = require('./typeof').isUndefined;

module.exports = function print(msg, options) {
    if (!isObject(options)) {
        options = {};
    }

    if (isUndefined(options.prefix)) {
        options.prefix = '[Guido] ';
    }
    console.log(`${options.prefix}${msg}`);
};
<commit_msg>print组件添加clearConsole功能<commit_after>'use strict';

const isObject = require('./typeof').isObject;
const clearConsole = require('./clearConsole');

module.exports = function print(msg, options = {}) {
    if (!isObject(options)) {
        options = {};
    }

    if (options.clear) {
        clearConsole();
    }

    console.log(`${(options.prefix || '')}${msg}`);
};
<|endoftext|>


<commit_before>'use strict';
import GenBase from '../genBase';

module.exports = class Generator extends GenBase {
  constructor(...args) {
    super(...args);
  }

  get prompting() {
    return function () {
      this.askForModuleName();
    };
  }

  get writing() {
    return async function () {
      const done = this.async();

      await Promise.all([
        this.copySrcFile('value'),
        this.copyUnitTest('value')
      ]);

      done();
    };
  }
};
<commit_msg>refactor(value): convert class to object<commit_after>'use strict';
import genBase from '../genBase';

module.exports = genBase.extend({
  prompting() {
    this.askForModuleName();
  },

  async writing() {
    const done = this.async();

    await Promise.all([
      this.copySrcFile('value'),
      this.copyUnitTest('value')
    ]);

    done();
  }
});
<|endoftext|>


<commit_before>/* A JS library for dealing with n-dimensional vectors.
 * Referenced from numpy.
 *
 * Project-Name : Ndime.
 * Code-Name : numjs.
 * Version : 0.6.
 * Author : Anubhav Tiwari <atworkstudios@gmail.com>
 */

class Vector{
	constructor(shape=[],arr=[]){
		this.array = arr;
		this.shape = ((shape.length)>0) ? shape : (this.calc_shape(this.array));
		this.size = this.calc_size(this.shape);
		this.dim = this.find_dim();
		this.flat = [];
		this.flatten(this.array);
	}

	/* class specific (static) methods */
    /* form a new vector for the given array */
	static array(arr){
		return new Vector([],arr);
	}

    /* make a new zero Vector */
	static zeroes(shape){
		var arr;
		if(shape.length == 1){
			arr = Vector.fill(shape[0],0);
		}
		else{
			var base_arr = Vector.fill(shape[shape.length-1],0);
			for(var i=shape.length-2; i>=0; i--){
				arr = [];
				for(var j=0; j<shape[i]; j++){
					arr.push(base_arr);
				}
				base_arr = arr;
			}
		}
		return new Vector(shape,arr);
	}

   /* sum of 2 vectors */
   static add(v1,v2){
	   if(v1.size === v2.size){
		   var sum = [];
		   for(var i=0; i<v1.flat.length; i++){
			   sum[i] = v1.flat[i] + v2.flat[i];
		   }
		   var v = new Vector(v1.shape);
		   v.arrange(sum);
		   return v;
	   }
	   else{
		   return new Error("Unequal Size");
	   }
   }

   /* fills the vector acc to passed args */
   static fill(len, ...args){
		var arr = [];
	  var i;
		if(!args || args.length === 0){
			for(i=0; i<len; i++){
				arr[i] = Math.random();
			}
		}
		else{
			if(args.length === 1){
				if(Array.isArray(args[0])){
					var j=0;
					for(i=0; i<len; i++){
						arr[i] = args[0][j++];
						if(j>=args[0].length){
							j=0;
						}
					}
				}
				else{
					for(i=0; i<len; i++){
						arr[i] = args[0];
					}
				}
			}
			else{
				var min;
				var num = min = args[0];
				var max = args[1];
				for(i=0; i<len; i++){
					arr[i] = num++;
					if(num>max){
						num = min;
					}
				}
			}
		}
		return arr;
	}

 /* -------------------------------------------------------------------------------------------------------------------------------------------- */

	/* object specific (property) methods */

	/* find the shape of the given array */

	find_dim(){
		return this.shape.length;
	}

	calc_shape(arr){
		var shape = [];
		shape.push(arr.length);
		var a = arr[0];
		while(Array.isArray(a)){
			shape.push(a.length);
			a = a[0];
		}
		return shape;
	}

	/* find the size of the array */
	calc_size(shape){
		var size = 1;
		for(var i of shape){
			size *= i;
		}
		return size;
	}

	/* function to convert n-dimension array into 1-D array */

	flatten(arr){
		for(var i of arr){
			if(Array.isArray(i)){
				this.flatten(i);
			}
			else{
				this.flat.push(i);
			}
	    }
	}

	/* a method to arrange or create a Vector from the given elements */
	arrange(elems_arr){
		var dim = this.dim;
		var base_arr_size = this.shape[dim-1];
		var final_arr = [];
		var base_elems = 1, j=0;
		if(dim >= 2){
			base_elems = this.shape[dim-2];
		}
		for(var i=0; i<base_elems; i++){
			if(elems_arr){
				var part = [];
				for(var k=0; k<base_arr_size; k++){
					part[k] = elems_arr[j++];
					if(j>=elems_arr.length){
					j=0;
					}
				}
				final_arr.push(Vector.fill(base_arr_size,part));
			}
			else{
				final_arr.push(Vector.fill(base_arr_size));
			}
		}
		this.array = final_arr;
		this.flat = [];
		this.flatten(this.array);
	}

	/* reshapes the vector only if for the new shape the number of elements remain same */
	reshape(new_shape){
		if(this.calc_size(new_shape) === this.size){
			/* reshape */
			var temp_arr = this.flat;
			this.shape = new_shape;
			this.dim = this.find_dim();
			this.flat = [];
			this.arrange(temp_arr);
		}
		else{
			return new Error("Resizing error : can't change the size");
		}
	}

	/* changes the shape and size of the vector in place */
	resize(new_shape){
		var temp_arr = this.flat;
		this.shape = new_shape;
		this.size = this.calc_size(this.shape);
		this.dim = this.find_dim();
		this.flat = [];
		this.arrange(temp_arr);
	}

	/* function to find the transpose */
	transpose(){
		/* converts row <-> columns */
		/* not that useful to main project as of now */
	}

	/* more to come */
}

/* some generic array methods */
function product(arr1,arr2){
	var i;
	var prod;
	if(Array.isArray(arr2)){
		var j=0;
		if(arr1.length === arr2.length){
			prod = [];
			arr1.forEach((i)=>{
				if(Array.isArray(i)){
					prod.push(product(i,arr2[j++]));
				}
				else{
					prod.push(i*arr2[j++]);
				}
			});
		}
		else{
			throw new Error("Uneven size!");
		}
	}
	else{
		prod = [];
		arr1.forEach((i)=>{
			if(Array.isArray(i)){
				prod.push(product(i,arr2));
			}
			else{
				prod.push(i*arr2);
			}
		})
	}
	return prod;
}

function sum(arr1,arr2){
	var i;
	var sum;
	if(arr2){
		if(Array.isArray(arr2)){
			if(arr1.length === arr2.length){
				sum = [];
				for(i=0; i<arr1.length; i++){
					sum[i] = arr1[i] + arr2[i];
				}
				return sum;
			}
			else{
				throw new Error("Uneven size!");
			}
		}
		else{
			sum = [];
			for(i=0; i<arr1.length; i++){
				sum[i] = arr1[i]+arr2;
			}
			return sum;
		}
	}
	else{
		sum = 0;
		for(i=0; i<arr1.length; i++){
			sum += arr1[i];
		}
		return sum;
	}
}

var vect_obj = {
	sum : sum,
	product : product,
	Vector : Vector
};

module.exports = vect_obj;
<commit_msg>fixed product<commit_after>/* A JS library for dealing with n-dimensional vectors.
 * Referenced from numpy.
 *
 * Project-Name : Ndime.
 * Code-Name : numjs.
 * Version : 0.6.
 * Author : Anubhav Tiwari <atworkstudios@gmail.com>
 */

class Vector{
	constructor(shape=[],arr=[]){
		this.array = arr;
		this.shape = ((shape.length)>0) ? shape : (this.calc_shape(this.array));
		this.size = this.calc_size(this.shape);
		this.dim = this.find_dim();
		this.flat = [];
		this.flatten(this.array);
	}

	/* class specific (static) methods */
    /* form a new vector for the given array */
	static array(arr){
		return new Vector([],arr);
	}

    /* make a new zero Vector */
	static zeroes(shape){
		var arr;
		if(shape.length == 1){
			arr = Vector.fill(shape[0],0);
		}
		else{
			var base_arr = Vector.fill(shape[shape.length-1],0);
			for(var i=shape.length-2; i>=0; i--){
				arr = [];
				for(var j=0; j<shape[i]; j++){
					arr.push(base_arr);
				}
				base_arr = arr;
			}
		}
		return new Vector(shape,arr);
	}

   /* sum of 2 vectors */
   static add(v1,v2){
	   if(v1.size === v2.size){
		   var sum = [];
		   for(var i=0; i<v1.flat.length; i++){
			   sum[i] = v1.flat[i] + v2.flat[i];
		   }
		   var v = new Vector(v1.shape);
		   v.arrange(sum);
		   return v;
	   }
	   else{
		   return new Error("Unequal Size");
	   }
   }

   /* fills the vector acc to passed args */
   static fill(len, ...args){
		var arr = [];
	  var i;
		if(!args || args.length === 0){
			for(i=0; i<len; i++){
				arr[i] = Math.random();
			}
		}
		else{
			if(args.length === 1){
				if(Array.isArray(args[0])){
					var j=0;
					for(i=0; i<len; i++){
						arr[i] = args[0][j++];
						if(j>=args[0].length){
							j=0;
						}
					}
				}
				else{
					for(i=0; i<len; i++){
						arr[i] = args[0];
					}
				}
			}
			else{
				var min;
				var num = min = args[0];
				var max = args[1];
				for(i=0; i<len; i++){
					arr[i] = num++;
					if(num>max){
						num = min;
					}
				}
			}
		}
		return arr;
	}

 /* -------------------------------------------------------------------------------------------------------------------------------------------- */

	/* object specific (property) methods */

	/* find the shape of the given array */

	find_dim(){
		return this.shape.length;
	}

	calc_shape(arr){
		var shape = [];
		shape.push(arr.length);
		var a = arr[0];
		while(Array.isArray(a)){
			shape.push(a.length);
			a = a[0];
		}
		return shape;
	}

	/* find the size of the array */
	calc_size(shape){
		var size = 1;
		for(var i of shape){
			size *= i;
		}
		return size;
	}

	/* function to convert n-dimension array into 1-D array */

	flatten(arr){
		for(var i of arr){
			if(Array.isArray(i)){
				this.flatten(i);
			}
			else{
				this.flat.push(i);
			}
	    }
	}

	/* a method to arrange or create a Vector from the given elements */
	arrange(elems_arr){
		var dim = this.dim;
		var base_arr_size = this.shape[dim-1];
		var final_arr = [];
		var base_elems = 1, j=0;
		if(dim >= 2){
			base_elems = this.shape[dim-2];
		}
		for(var i=0; i<base_elems; i++){
			if(elems_arr){
				var part = [];
				for(var k=0; k<base_arr_size; k++){
					part[k] = elems_arr[j++];
					if(j>=elems_arr.length){
					j=0;
					}
				}
				final_arr.push(Vector.fill(base_arr_size,part));
			}
			else{
				final_arr.push(Vector.fill(base_arr_size));
			}
		}
		this.array = final_arr;
		this.flat = [];
		this.flatten(this.array);
	}

	/* reshapes the vector only if for the new shape the number of elements remain same */
	reshape(new_shape){
		if(this.calc_size(new_shape) === this.size){
			/* reshape */
			var temp_arr = this.flat;
			this.shape = new_shape;
			this.dim = this.find_dim();
			this.flat = [];
			this.arrange(temp_arr);
		}
		else{
			return new Error("Resizing error : can't change the size");
		}
	}

	/* changes the shape and size of the vector in place */
	resize(new_shape){
		var temp_arr = this.flat;
		this.shape = new_shape;
		this.size = this.calc_size(this.shape);
		this.dim = this.find_dim();
		this.flat = [];
		this.arrange(temp_arr);
	}

	/* function to find the transpose */
	transpose(){
		/* converts row <-> columns */
		/* not that useful to main project as of now */
	}

	/* more to come */
}

/* some generic array methods */
function product(arr1,arr2){
	var i = 0,prod = [];
	if(!Array.isArray(arr1) && !Array.isArray(arr2)){
		return arr1*arr2;
	}
	else{
		arr1.forEach((j)=>{
			if(Array.isArray(j)){
				prod.push(product(j,arr2));
			}
			else{
				if(Array.isArray(arr2)){
					if(arr1.length === arr2.length){
						prod.push(j*arr2[i++]);
					}
					else{
						throw new Error("Uneven Size!");
					}
				}
				else{
					prod.push(j*arr2);
				}
			}
		});
	}
	return prod;
}

function sum(arr1,arr2){
	var i;
	var sum;
	if(arr2){
		if(Array.isArray(arr2)){
			if(arr1.length === arr2.length){
				sum = [];
				for(i=0; i<arr1.length; i++){
					sum[i] = arr1[i] + arr2[i];
				}
				return sum;
			}
			else{
				throw new Error("Uneven size!");
			}
		}
		else{
			sum = [];
			for(i=0; i<arr1.length; i++){
				sum[i] = arr1[i]+arr2;
			}
			return sum;
		}
	}
	else{
		sum = 0;
		for(i=0; i<arr1.length; i++){
			sum += arr1[i];
		}
		return sum;
	}
}

var vect_obj = {
	sum : sum,
	product : product,
	Vector : Vector
};

module.exports = vect_obj;
<|endoftext|>


<commit_before>var Queue = require('./Queue.js');

/*
 This should plan the schedules, given some candidate classes.
 */

/* finds the intersection of
 * two arrays in a simple fashion.
 *
 * params must already be sorted
 * from http://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript
 */
function intersect_safe(a, b)
{
    var ai=0, bi=0;
    var result = [];

    while( ai < a.length && bi < b.length )
    {
        if      (a[ai] < b[bi] ){ ai++; }
        else if (a[ai] > b[bi] ){ bi++; }
        else /* they're equal */
        {
            result.push(a[ai]);
            ai++;
            bi++;
        }
    }

    return result;
}

function timeToMinutes(time) {
    var s = time.split(':');
    return parseInt(s[0]) * 60 + parseInt(s[1]);
}

function ScheduleTime(days, startTime, endTime) {
    this.days = days.split("").slice();
    this.days.sort();

    this.startTime = timeToMinutes(startTime);
    this.endTime = timeToMinutes(endTime);

    this.overlaps = function(b) {
        var days = intersect_safe(this.days, b.days);
        if(days.length == 0) {
            return false;
        } else {
            return (this.startTime <= b.endTime) && (b.startTime <= this.endTime);
        }
    };
}

function schedulesOverlap(a, b) {
    return a.overlaps(b);
}

// var x = new ScheduleTime("MWF", "10:00", "12:29");
// var y = new ScheduleTime("WF", "10:30", "12:29");
// var z = new ScheduleTime("R", "10:30", "12:29");
// var a = new ScheduleTime("R", "14:30", "15:29");

// constraints
// [class, class, class], find a time for each class
// {0: .., 1: ..., x: ..}, pick only one section out of 0, 1, .., x
// {LEC: [...], DIS: [...]}, pick exactly one of each in LEC, DIS, ...

function addScheduleTime(sections) {
    for(var section in sections) {
        var components = sections[section];
        for(var comp in components) {
            var rows = components[comp];
            for(var i = 0; i < rows.length; i += 1) {
                var row = rows[i];
                row['ScheduleTime'] = new ScheduleTime(row['Meeting Days'], row['Start Time'], row['End Time']);
                rows[i] = row;
            }
        }
    }
    return sections;
}

function classSections(classes) {
    var out = [];

    for(var i = 0; i < classes.length; i += 1) {
        var sections = classes[i]['data']['sections'];
        sections = addScheduleTime(sections);
        out.push(sections);
    }
    console.log(out);
    return out;
}

// picked = [[c1, c2], [c3, c4], ...]
// items = [c1, c2, c3]

function checkOverlap(stime, picked, items) {
    for(var i = 0; i < items.length; i += 1) {
        var item = items[i];
        if(item['ScheduleTime'].overlaps(stime)) {
            return true;
        }
    }
    for(var i = 0; i < picked.length; i += 1) {
        for(var j = 0; j < picked[i].length; j += 1) {
            var item = picked[i][j];
            if(item['ScheduleTime'].overlaps(stime)) {
                return true;
            }
        }
    }

    return false;
}

function possibleCombos(sections, picked) {
    // all possible combinations of classes
    // TODO: write function that lists possibilities, given picked so far (exclude overlapping times)
    var possible = [];

    for(var section in sections) {
        var components = sections[section];
        var keys = Object.keys(components);

        var q = new Queue();
        q.enqueue([[], 0]);

        while(!q.isEmpty()) {
            var state = q.dequeue();
            var items = state[0];
            var key_ix = state[1];

            if(key_ix >= keys.length) {
                possible.push(items);
                continue;
            }

            var comp = keys[key_ix];
            var rows = components[comp];

            for(var i = 0; i < rows.length; i += 1) {
                var row = rows[i];
                if(!checkOverlap(row['ScheduleTime'], picked, items)) {
                    var items_new = items.slice();
                    items_new.push(row);
                    var state_new = [items_new, key_ix + 1];
                    q.enqueue(state_new);
                }
            }

        }
    }

    return possible;
}

function proposePossible(classes) {
    if(classes.length == 0) {
        return [];
    }

    // state is (picked, next_index)

    var possible = [];

    var q = new Queue();

    var state = [[], 0];
    q.enqueue(state);

    while(!q.isEmpty()) {
        state = q.dequeue();
        var picked = state[0].slice();
        var ix = state[1];
        if(ix >= classes.length) {
            possible.push(picked);
            continue;
        }

        var sections = classes[ix];
        var combos = possibleCombos(sections, picked);

        for(var i = 0; i < combos.length; i += 1) {
            var combo = combos[i];
            var picked_new = picked.slice();
            picked_new.push(combo);
            var state_new = [picked_new, ix+1];
            q.enqueue(state_new);
        }
    }

    return possible;
}

function possibleCalendars(classes) {
    var csections = classSections(classes);
    return proposePossible(csections);
}

module.exports = {
    possibleCalendars: possibleCalendars
};
<commit_msg>cleanup planner<commit_after>var Queue = require('./Queue.js');

/*
 This should plan the schedules, given some candidate classes.
 */

/* finds the intersection of
 * two arrays in a simple fashion.
 *
 * params must already be sorted
 * from http://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript
 */
function intersect_safe(a, b)
{
    var ai=0, bi=0;
    var result = [];

    while( ai < a.length && bi < b.length )
    {
        if      (a[ai] < b[bi] ){ ai++; }
        else if (a[ai] > b[bi] ){ bi++; }
        else /* they're equal */
        {
            result.push(a[ai]);
            ai++;
            bi++;
        }
    }

    return result;
}

function timeToMinutes(time) {
    var s = time.split(':');
    return parseInt(s[0]) * 60 + parseInt(s[1]);
}

function ScheduleTime(days, startTime, endTime) {
    this.days = days.split("").slice();
    this.days.sort();

    this.startTime = timeToMinutes(startTime);
    this.endTime = timeToMinutes(endTime);

    this.overlaps = function(b) {
        var days = intersect_safe(this.days, b.days);
        if(days.length == 0) {
            return false;
        } else {
            return (this.startTime <= b.endTime) && (b.startTime <= this.endTime);
        }
    };
}

function schedulesOverlap(a, b) {
    return a.overlaps(b);
}

// constraints
// [class, class, class], find a time for each class
// {0: .., 1: ..., x: ..}, pick only one section out of 0, 1, .., x
// {LEC: [...], DIS: [...]}, pick exactly one of each in LEC, DIS, ...

function addScheduleTime(sections) {
    for(var section in sections) {
        var components = sections[section];
        for(var comp in components) {
            var rows = components[comp];
            for(var i = 0; i < rows.length; i += 1) {
                var row = rows[i];
                row['ScheduleTime'] = new ScheduleTime(row['Meeting Days'], row['Start Time'], row['End Time']);
                rows[i] = row;
            }
        }
    }
    return sections;
}

function classSections(classes) {
    var out = [];

    for(var i = 0; i < classes.length; i += 1) {
        var sections = classes[i]['data']['sections'];
        sections = addScheduleTime(sections);
        out.push(sections);
    }
    console.log(out);
    return out;
}

// picked = [[c1, c2], [c3, c4], ...]
// items = [c1, c2, c3]

function checkOverlap(stime, picked, items) {
    for(var i = 0; i < items.length; i += 1) {
        var item = items[i];
        if(item['ScheduleTime'].overlaps(stime)) {
            return true;
        }
    }
    for(var i = 0; i < picked.length; i += 1) {
        for(var j = 0; j < picked[i].length; j += 1) {
            var item = picked[i][j];
            if(item['ScheduleTime'].overlaps(stime)) {
                return true;
            }
        }
    }

    return false;
}

function possibleCombos(sections, picked) {
    // all possible combinations of classes
    // lists possibilities, given picked so far (exclude overlapping times)
    var possible = [];

    for(var section in sections) {
        var components = sections[section];
        var keys = Object.keys(components);

        // state is picked, key_ix

        var q = new Queue();
        q.enqueue([[], 0]);

        while(!q.isEmpty()) {
            var state = q.dequeue();
            var items = state[0];
            var key_ix = state[1];

            if(key_ix >= keys.length) {
                possible.push(items);
                continue;
            }

            var comp = keys[key_ix];
            var rows = components[comp];

            for(var i = 0; i < rows.length; i += 1) {
                var row = rows[i];
                if(!checkOverlap(row['ScheduleTime'], picked, items)) {
                    var items_new = items.slice();
                    items_new.push(row);
                    var state_new = [items_new, key_ix + 1];
                    q.enqueue(state_new);
                }
            }

        }
    }

    return possible;
}

function proposePossible(classes) {
    if(classes.length == 0) {
        return [];
    }

    // state is (picked, next_index)

    var possible = [];

    var q = new Queue();

    var state = [[], 0];
    q.enqueue(state);

    while(!q.isEmpty()) {
        state = q.dequeue();
        var picked = state[0].slice();
        var ix = state[1];
        if(ix >= classes.length) {
            possible.push(picked);
            continue;
        }

        var sections = classes[ix];
        var combos = possibleCombos(sections, picked);

        for(var i = 0; i < combos.length; i += 1) {
            var combo = combos[i];
            var picked_new = picked.slice();
            picked_new.push(combo);
            var state_new = [picked_new, ix+1];
            q.enqueue(state_new);
        }
    }

    return possible;
}

function possibleCalendars(classes) {
    var csections = classSections(classes);
    return proposePossible(csections);
}

module.exports = {
    possibleCalendars: possibleCalendars
};
<|endoftext|>


<commit_before>/**
 * Winston SQS
 * A Winston transpot that uses Amazon SQS to send messages.
 * MIT License
 */

var aws         = require("aws-sdk"),
    assert      = require("assert"),
    winston     = require("winston"),
    util        = require("util");

var SQS = winston.transports.SQS = module.exports = exports.SQS =  function (options) {

    if (!options.aws_accesskeyid) {
        throw new Error("AWS options.aws_accesskeyid is required");
    }
    if (!options.aws_secretaccesskey) {
        throw new Error("AWS options.aws_secretaccesskey is required");
    }

    options         = options || {};

    winston.Transport.call(this, options);

    this.name       = 'sqs';
    this.timestamp  = options.timestamp !== false;

    this.queueurl   = options.aws_queueurl;
    this.client     = new aws.SQS({
        credentials  : new aws.Credentials(options.aws_accesskeyid, options.aws_secretaccesskey),
        region : options.aws_region || "us-east-1",
        sslEnabled :  options.aws_sslenabled || true,
        maxRetries :  options.aws_maxretries || 3
    });
    this.debug = options.debug || false;
};

SQS.SQS = SQS;

util.inherits(SQS, winston.Transport);

//
// ### function log (level, msg, [meta], callback)
// #### @level {string} Level at which to log the message.
// #### @msg {string} Message to log
// #### @meta {Object} **Optional** Additional metadata to attach
// #### @callback {function} Continuation to respond to when complete.
// Core logging method exposed to Winston.  Metadata is optional.
//
SQS.prototype.log = function( level, msg, meta, callback) {

    if (this.silent) {
        return callback(null, true);
    }

    if (typeof meta === 'function' && arguments.length == 3) {
        callback = meta;
        meta = {};
    }

    var output = formatLog({
        level:       level,
        message:     msg,
        meta:        meta,
        timestamp:   this.timestamp,
        formatter:   this.formatter
    });

    var self = this;

    this.client.sendMessage({ QueueUrl : this.queueurl, MessageBody : output}, function(err, response) {
        if (self.debug) {
            console.log("winston-sqs.sendMessage err=", err, ", response=", response);
        }
        callback(err, !!response);
    });

    return null; // make linter happy
};

function formatLog(options) {
    if (typeof options.formatter == 'function') {
        return String(options.formatter(winston.clone(options)));
    }

    var output = new Date().toISOString();
    output += ' : ';
    output += options.level;
    output += ' : ';
    output += options.message;
    output += ' : ';

    var meta = options.meta;
    if (meta !== null && meta !== undefined) {
        if (typeof meta !== 'object') {
            output += meta;
        }
        else if (Object.keys(meta).length > 0) {
            try {
             output += JSON.stringify(meta);
            }
            catch(err) {
                output += "metadata could not be output likely due to circular reference";
            }
        }
    }

    return output;
}
<commit_msg>Log the first sendMessage error<commit_after>/**
 * Winston SQS
 * A Winston transpot that uses Amazon SQS to send messages.
 * MIT License
 */

var aws         = require("aws-sdk"),
    assert      = require("assert"),
    winston     = require("winston"),
    util        = require("util");

var SQS = winston.transports.SQS = module.exports = exports.SQS =  function (options) {

    if (!options.aws_accesskeyid) {
        throw new Error("AWS options.aws_accesskeyid is required");
    }
    if (!options.aws_secretaccesskey) {
        throw new Error("AWS options.aws_secretaccesskey is required");
    }

    options         = options || {};

    winston.Transport.call(this, options);

    this.name       = 'sqs';
    this.timestamp  = options.timestamp !== false;

    this.queueurl   = options.aws_queueurl;
    this.client     = new aws.SQS({
        credentials  : new aws.Credentials(options.aws_accesskeyid, options.aws_secretaccesskey),
        region : options.aws_region || "us-east-1",
        sslEnabled :  options.aws_sslenabled || true,
        maxRetries :  options.aws_maxretries || 3
    });
    this.debug = options.debug || false;

    // private
    this._noErrorYet = true;
};

SQS.SQS = SQS;

util.inherits(SQS, winston.Transport);

//
// ### function log (level, msg, [meta], callback)
// #### @level {string} Level at which to log the message.
// #### @msg {string} Message to log
// #### @meta {Object} **Optional** Additional metadata to attach
// #### @callback {function} Continuation to respond to when complete.
// Core logging method exposed to Winston.  Metadata is optional.
//
SQS.prototype.log = function( level, msg, meta, callback) {

    if (this.silent) {
        return callback(null, true);
    }

    if (typeof meta === 'function' && arguments.length == 3) {
        callback = meta;
        meta = {};
    }

    var output = formatLog({
        level:       level,
        message:     msg,
        meta:        meta,
        timestamp:   this.timestamp,
        formatter:   this.formatter
    });

    var self = this;

    this.client.sendMessage({ QueueUrl : this.queueurl, MessageBody : output}, function(err, response) {
        // Log the first error but keep silent afterwards not to spam the output
        if (err && self._noErrorYet) {
            self._noErrorYet = false;
            console.warn("winston-sqs: Sending a message to " + self.queueurl + " failed",
                         err,
                         "(No further errors will be printed.)");
        }
        if (self.debug) {
            console.log("winston-sqs.sendMessage err=", err, ", response=", response);
        }
        callback(err, !!response);
    });

    return null; // make linter happy
};

function formatLog(options) {
    if (typeof options.formatter == 'function') {
        return String(options.formatter(winston.clone(options)));
    }

    var output = new Date().toISOString();
    output += ' : ';
    output += options.level;
    output += ' : ';
    output += options.message;
    output += ' : ';

    var meta = options.meta;
    if (meta !== null && meta !== undefined) {
        if (typeof meta !== 'object') {
            output += meta;
        }
        else if (Object.keys(meta).length > 0) {
            try {
             output += JSON.stringify(meta);
            }
            catch(err) {
                output += "metadata could not be output likely due to circular reference";
            }
        }
    }

    return output;
}
<|endoftext|>


<commit_before>var assert = require('assert');

module.exports = function formatText(text, options) {
  assert(text.shift() == 'text');

  var result = [];
  var numbers = [0, 0, 0, 0];

  var index = 0;
  while (index < text.length) {
    var block = text[index++];
    if (block[0] != 'row') {
      result.push(formatBlock(block, numbers));
    } else {
      // extract whole table
      var table = [];
      var cells = [block.slice(2)];
      while (index < text.length) {
        var block = text[index];
        if (block[0] === 'col') {
          cells.push(block.slice(2));
          index++;
        } else if (block[0] === 'row') {
          table.push(cells);
          cells = [block.slice(2)];
          index++;
        } else {
          break;
        }
      };
      table.push(cells); // final row
      result.push(formatTable(table));
    }
  };

  var output = result.join('\n\n') + '\n';
  return output;
};

function formatBlock(block, numbers) {
  var type = block.shift();
  var attr = block.shift();

  var prefix = repeat('    ', attr.level);

  if (type === 'numitem') {
    numbers[attr.level]++;
  }
  // reset numbers for all levels below
  for (var i = attr.level+1; i <= 3; i++)
    numbers[i] = 0;

  switch (type) {
    case 'heading': return formatHeading(formatSpans(block), attr.level);
    case 'item': return formatSpans(block, prefix, repeat('    ', attr.level - 1) + '  * ');
    case 'numitem':
      var number = numbers[attr.level] + '. ';
      if (number.length < 4)
        number = ' ' + number;
      return formatSpans(block, prefix, repeat('    ', attr.level - 1) + number);
    case 'quote': return formatSpans(block, repeat('    ', attr.level - 1) + '  > ');
    case 'link':
      var linkId = block.length > 0 ? block.shift() : ['id', '?'];
      assert(linkId[0] === 'id');
      return formatSpans(block, '', '[' + linkId[1] + ']: ');
    case 'note':
      var linkId = block.length > 0 ? block.shift() : ['id', '?'];
      assert(linkId[0] === 'id');
      return formatSpans(block, '', '[^' + linkId[1] + ']: ');
    case 'verbatim':
      var border = repeat('~', 80);
      return border + '\n' + formatVerbatim(block) + '\n' + border;
    default: return formatSpans(block, prefix);
  };
};

function formatHeading(text, level) {
  switch (level) {
    case 1: return text + '\n' + repeat('=', text.length);
    case 2: return text + '\n' + repeat('-', text.length);
    default: return repeat('#', level) + ' ' + text;
  }
};

function formatSpans(spans, prefix, firstPrefix) {
  prefix = prefix || '';
  firstPrefix = firstPrefix || prefix;

  var maxLen = 80 - prefix.length;

  var lines = [];
  var line = '';
  spans.forEach(function(span) {
    if (span[0] == 'break') {
      lines.push(line.trim() + '  ');
      line = '';
      return;
    }

    var words = formatSpan(span).split(/(\S+\s+)/);
    words.forEach(function (word) {
      var joined = line + word;
      if (joined.length <= maxLen) {
        line = joined;
      } else {
        lines.push(line.trim());
        line = word;
      }
    });
  });
  if (line.length > 0)
    lines.push(line.trim());
  return firstPrefix + lines.join('\n' + prefix);
};

function formatSpan(span) {
  assert(span.length == 2);
  var type = span[0];
  var text = span[1];

  switch (type) {
    case 'emph': return '*' + escape(text) + '*';
    case 'strong': return '**' + escape(text) + '**';
    case 'code': return '`' + escape(text) + '`';
    case 'linktext': return '[' + escape(text) + ']';
    case 'linkref': return '[' + escape(text) + ']';
    case 'noteref': return '[^' + escape(text) + ']';
    case 'url': return '<' + escape(text) + '>';
    default: return escape(text);
  };
};

function formatTable(table) {
  var rows = table.length;
  var cols = table.reduce(function (val, row) { return Math.max(row.length, val); }, 1);

  var widths = [];
  for (var i = 0; i < cols; i++) {
    widths[i] = table.reduce(function (val, row) {
      var cell = row[i];
      var text = formatSpans(cell);
      return Math.max(text.length, val);
    }, 1);
  }

  var tableText = table.map(function (row) {
    var cellsText = row.map(function (cell, index) {
      var text = formatSpans(cell);
      return text + repeat(' ', widths[index] - text.length);
    });
    return '| ' + cellsText.join(' | ') + ' |';
  });

  var divider = '+' + widths.map(function (width) { return repeat('-', width + 2); }).join('+') + '+';
  return divider + '\n' + tableText.join('\n' + divider + '\n') + '\n' + divider;
};

function formatVerbatim(spans) {
  var text = spans.map(function (span) { return span[1]; });
  return text.join('');
};

function escape(str) {
  return str.
    replace(/\\/g,'\\\\').
    replace(/\*/g,'\\*').
    replace(/`/g,'\\`').
    replace(/\[/g,'\\[').
    replace(/\]/g,'\\]').
    replace(/</g,'\\<').
    replace(/>/g,'\\>');
};

function repeat(str, times) {
  return new Array(times+1).join(str);
};
<commit_msg>Implement math blocks and inlines formatting.<commit_after>var assert = require('assert');

module.exports = function formatText(text, options) {
  assert(text.shift() == 'text');

  var result = [];
  var numbers = [0, 0, 0, 0];

  var index = 0;
  while (index < text.length) {
    var block = text[index++];
    if (block[0] != 'row') {
      result.push(formatBlock(block, numbers));
    } else {
      // extract whole table
      var table = [];
      var cells = [block.slice(2)];
      while (index < text.length) {
        var block = text[index];
        if (block[0] === 'col') {
          cells.push(block.slice(2));
          index++;
        } else if (block[0] === 'row') {
          table.push(cells);
          cells = [block.slice(2)];
          index++;
        } else {
          break;
        }
      };
      table.push(cells); // final row
      result.push(formatTable(table));
    }
  };

  var output = result.join('\n\n') + '\n';
  return output;
};

function formatBlock(block, numbers) {
  var type = block.shift();
  var attr = block.shift();

  var prefix = repeat('    ', attr.level);

  if (type === 'numitem') {
    numbers[attr.level]++;
  }
  // reset numbers for all levels below
  for (var i = attr.level+1; i <= 3; i++)
    numbers[i] = 0;

  switch (type) {
    case 'heading': return formatHeading(formatSpans(block), attr.level);
    case 'item': return formatSpans(block, prefix, repeat('    ', attr.level - 1) + '  * ');
    case 'numitem':
      var number = numbers[attr.level] + '. ';
      if (number.length < 4)
        number = ' ' + number;
      return formatSpans(block, prefix, repeat('    ', attr.level - 1) + number);
    case 'quote': return formatSpans(block, repeat('    ', attr.level - 1) + '  > ');
    case 'link':
      var linkId = block.length > 0 ? block.shift() : ['id', '?'];
      assert(linkId[0] === 'id');
      return formatSpans(block, '', '[' + linkId[1] + ']: ');
    case 'note':
      var linkId = block.length > 0 ? block.shift() : ['id', '?'];
      assert(linkId[0] === 'id');
      return formatSpans(block, '', '[^' + linkId[1] + ']: ');
    case 'verbatim':
      var border = repeat('~', 80);
      return border + '\n' + formatVerbatim(block) + '\n' + border;
    case 'formula':
      return '$$\n' + formatVerbatim(block) + '\n$$';
    default: return formatSpans(block, prefix);
  };
};

function formatHeading(text, level) {
  switch (level) {
    case 1: return text + '\n' + repeat('=', text.length);
    case 2: return text + '\n' + repeat('-', text.length);
    default: return repeat('#', level) + ' ' + text;
  }
};

function formatSpans(spans, prefix, firstPrefix) {
  prefix = prefix || '';
  firstPrefix = firstPrefix || prefix;

  var maxLen = 80 - prefix.length;

  var lines = [];
  var line = '';
  spans.forEach(function(span) {
    if (span[0] == 'break') {
      lines.push(line.trim() + '  ');
      line = '';
      return;
    }

    var words = formatSpan(span).split(/(\S+\s+)/);
    words.forEach(function (word) {
      var joined = line + word;
      if (joined.length <= maxLen) {
        line = joined;
      } else {
        lines.push(line.trim());
        line = word;
      }
    });
  });
  if (line.length > 0)
    lines.push(line.trim());
  return firstPrefix + lines.join('\n' + prefix);
};

function formatSpan(span) {
  assert(span.length == 2);
  var type = span[0];
  var text = span[1];

  switch (type) {
    case 'emph': return '*' + escape(text) + '*';
    case 'strong': return '**' + escape(text) + '**';
    case 'code': return '`' + escape(text) + '`';
    case 'linktext': return '[' + escape(text) + ']';
    case 'linkref': return '[' + escape(text) + ']';
    case 'noteref': return '[^' + escape(text) + ']';
    case 'math': return '$' + escape(text) + '$';
    case 'url': return '<' + escape(text) + '>';
    default: return escape(text);
  };
};

function formatTable(table) {
  var rows = table.length;
  var cols = table.reduce(function (val, row) { return Math.max(row.length, val); }, 1);

  var widths = [];
  for (var i = 0; i < cols; i++) {
    widths[i] = table.reduce(function (val, row) {
      var cell = row[i];
      var text = formatSpans(cell);
      return Math.max(text.length, val);
    }, 1);
  }

  var tableText = table.map(function (row) {
    var cellsText = row.map(function (cell, index) {
      var text = formatSpans(cell);
      return text + repeat(' ', widths[index] - text.length);
    });
    return '| ' + cellsText.join(' | ') + ' |';
  });

  var divider = '+' + widths.map(function (width) { return repeat('-', width + 2); }).join('+') + '+';
  return divider + '\n' + tableText.join('\n' + divider + '\n') + '\n' + divider;
};

function formatVerbatim(spans) {
  var text = spans.map(function (span) { return span[1]; });
  return text.join('');
};

function escape(str) {
  return str.
    replace(/\\/g,'\\\\').
    replace(/\*/g,'\\*').
    replace(/`/g,'\\`').
    replace(/\[/g,'\\[').
    replace(/\]/g,'\\]').
    replace(/</g,'\\<').
    replace(/>/g,'\\>');
};

function repeat(str, times) {
  return new Array(times+1).join(str);
};
<|endoftext|>


<commit_before>function SetUserGroupPermissions($scope, navigationService, notificationsService, $http) {

    // Variables used in the view.
    $scope.pageName = $scope.currentNode.name;
    $scope.userOptions = {
        applyPermissions: false
    };
    $scope.processingMessage = "Processing request. Please wait.";
    $scope.successMessage = "Operation successful.";
    $scope.failureMessage = "An unknown error occurred.";
    $scope.showSelection = false;
    $scope.showConfirmButtons = false;
    $scope.showSuccess = false;
    $scope.showFailure = false;
    $scope.showDoneButton = false;
    $scope.showProgress = true;
    $scope.applyPermissionsId = "ugp-apply-permissions-" + Math.random().toString().replace(".", "");
    $scope.userTypes = [];
    $scope.permissions = [];

    // Gets permissions from the server.
    function getPermissions() {

        // Variables.
        var id = parseInt($scope.currentNode.id);
        var url = "/umbraco/backoffice/UGP/UserGroupPermissions/GetGroupPermissions";
        var options = {
            cache: false,
            params: {
                "NodeId": id,
                // Cache buster ensures requests aren't cached.
                "CacheBuster": Math.random()
            }
        };

        // Request user type permissions from server.
        $http.get(url, options).success(function (data) {

            // Set scope variables based on permissions.
            $scope.userTypes = data.UserTypePermissions;
            for (var i = 0; i < data.UserTypePermissions[0].Permissions.length; i++) {
                var permission = data.UserTypePermissions[0].Permissions[i];
                var userTypes = [];
                for (var j = 0; j < data.UserTypePermissions.length; j++) {
                    var userType = data.UserTypePermissions[j];
                    userTypes.push({
                        UserTypeId: userType.UserTypeId,
                        HasPermission: userType.Permissions[i].HasPermission
                    });
                }
                $scope.permissions.push({
                    Label: permission.Label,
                    Letter: permission.Letter,
                    UserTypes: userTypes
                });
            }

            // Update UI.
            $scope.showProgress = false;
            $scope.showSelection = true;
            $scope.showConfirmButtons = true;

        });
    }
    getPermissions();

    // Update the group permissions.
    $scope.updatePermissions = function () {

        // Store permissions by user type ID.
        var userTypePermissions = {};
        for (var i = 0; i < $scope.permissions.length; i++) {
            var permission = $scope.permissions[i];
            for (var j = 0; j < permission.UserTypes.length; j++) {
                var userType = permission.UserTypes[j];
                if (userType.HasPermission) {
                    var existingUserType = userTypePermissions[userType.UserTypeId];
                    existingUserType = existingUserType || {
                        UserTypeId: userType.UserTypeId,
                        Permissions: []
                    };
                    existingUserType.Permissions.push(permission.Letter);
                    userTypePermissions[userType.UserTypeId] = existingUserType;
                }
            }
        }

        // Convert permissions to format expected by server.
        var dataPermissions = [];
        for (var i = 0; i < $scope.permissions[0].UserTypes.length; i++) {
            var userTypeId = $scope.permissions[0].UserTypes[i].UserTypeId;
            dataPermissions.push(userTypePermissions[userTypeId]);
        }

        // Variables.
        var id = parseInt($scope.currentNode.id);
        var url = "/umbraco/backoffice/UGP/UserGroupPermissions/SetGroupPermissions";
        var data = {
            "NodeId": id,
            "ReplacePermissionsOnUsers": $scope.userOptions.applyPermissions,
            "UserTypePermissions": dataPermissions
        };
        var strData = JSON.stringify(data);
        var options = {
            headers: {
                "Content-Type": "application/json"
            }
        };

        // Send request to update permissions.
        $scope.showProgress = true;
        $scope.showSelection = false;
        $scope.showConfirmButtons = false;
        $http.post(url, strData, options).success(function (data) {

            // Was the request successful?
            if (data.Success) {
                $scope.successMessage = "The permissions were successfully updated.";
                $scope.showSuccess = true;
            } else {
                $scope.failureMessage = data.Reason;
                $scope.showFailure = true;
                notificationsService.error("Unexpected Error", data.Reason);
            }
            $scope.showProgress = false;
            $scope.showDoneButton = true;

        })
        .error(function () {

            // An error occurred.
            $scope.showProgress = false;
            $scope.showFailure = true;
            $scope.showDoneButton = true;
            $scope.failureMessage = "There was an issue communicating with the server.";
            notificationsService.error("Server Error", $scope.failureMessage);

        });

    };

    // Cancel.
    $scope.cancel = function () {
        navigationService.hideDialog();
    };

    // Close dialog.
    $scope.closeDialog = function () {
        navigationService.hideDialog();
    };

}

angular.module("umbraco").controller("UGP.SetUserGroupPermissions", SetUserGroupPermissions);<commit_msg>Fixed an error when no permissions are selected for a given user type: https://github.com/Nicholas-Westby/usergrouppermissions/issues/8#issuecomment-160923700<commit_after>function SetUserGroupPermissions($scope, navigationService, notificationsService, $http) {

    // Variables used in the view.
    $scope.pageName = $scope.currentNode.name;
    $scope.userOptions = {
        applyPermissions: false
    };
    $scope.processingMessage = "Processing request. Please wait.";
    $scope.successMessage = "Operation successful.";
    $scope.failureMessage = "An unknown error occurred.";
    $scope.showSelection = false;
    $scope.showConfirmButtons = false;
    $scope.showSuccess = false;
    $scope.showFailure = false;
    $scope.showDoneButton = false;
    $scope.showProgress = true;
    $scope.applyPermissionsId = "ugp-apply-permissions-" + Math.random().toString().replace(".", "");
    $scope.userTypes = [];
    $scope.permissions = [];

    // Gets permissions from the server.
    function getPermissions() {

        // Variables.
        var id = parseInt($scope.currentNode.id);
        var url = "/umbraco/backoffice/UGP/UserGroupPermissions/GetGroupPermissions";
        var options = {
            cache: false,
            params: {
                "NodeId": id,
                // Cache buster ensures requests aren't cached.
                "CacheBuster": Math.random()
            }
        };

        // Request user type permissions from server.
        $http.get(url, options).success(function (data) {

            // Set scope variables based on permissions.
            $scope.userTypes = data.UserTypePermissions;
            for (var i = 0; i < data.UserTypePermissions[0].Permissions.length; i++) {
                var permission = data.UserTypePermissions[0].Permissions[i];
                var userTypes = [];
                for (var j = 0; j < data.UserTypePermissions.length; j++) {
                    var userType = data.UserTypePermissions[j];
                    userTypes.push({
                        UserTypeId: userType.UserTypeId,
                        HasPermission: userType.Permissions[i].HasPermission
                    });
                }
                $scope.permissions.push({
                    Label: permission.Label,
                    Letter: permission.Letter,
                    UserTypes: userTypes
                });
            }

            // Update UI.
            $scope.showProgress = false;
            $scope.showSelection = true;
            $scope.showConfirmButtons = true;

        });
    }
    getPermissions();

    // Update the group permissions.
    $scope.updatePermissions = function () {

        // Store permissions by user type ID.
        var userTypePermissions = {};
        for (var i = 0; i < $scope.permissions.length; i++) {
            var permission = $scope.permissions[i];
            for (var j = 0; j < permission.UserTypes.length; j++) {
                var userType = permission.UserTypes[j];
                var existingUserType = userTypePermissions[userType.UserTypeId];
                existingUserType = existingUserType || {
                    UserTypeId: userType.UserTypeId,
                    Permissions: []
                };
                userTypePermissions[userType.UserTypeId] = existingUserType;
                if (userType.HasPermission) {
                    existingUserType.Permissions.push(permission.Letter);
                }
            }
        }

        // Convert permissions to format expected by server.
        var dataPermissions = [];
        for (var i = 0; i < $scope.permissions[0].UserTypes.length; i++) {
            var userTypeId = $scope.permissions[0].UserTypes[i].UserTypeId;
            var permission = userTypePermissions[userTypeId];
            if (permission) {
                dataPermissions.push(userTypePermissions[userTypeId]);
            }
        }

        // Variables.
        var id = parseInt($scope.currentNode.id);
        var url = "/umbraco/backoffice/UGP/UserGroupPermissions/SetGroupPermissions";
        var data = {
            "NodeId": id,
            "ReplacePermissionsOnUsers": $scope.userOptions.applyPermissions,
            "UserTypePermissions": dataPermissions
        };
        var strData = JSON.stringify(data);
        var options = {
            headers: {
                "Content-Type": "application/json"
            }
        };

        // Send request to update permissions.
        $scope.showProgress = true;
        $scope.showSelection = false;
        $scope.showConfirmButtons = false;
        $http.post(url, strData, options).success(function (data) {

            // Was the request successful?
            if (data.Success) {
                $scope.successMessage = "The permissions were successfully updated.";
                $scope.showSuccess = true;
            } else {
                $scope.failureMessage = data.Reason;
                $scope.showFailure = true;
                notificationsService.error("Unexpected Error", data.Reason);
            }
            $scope.showProgress = false;
            $scope.showDoneButton = true;

        })
        .error(function () {

            // An error occurred.
            $scope.showProgress = false;
            $scope.showFailure = true;
            $scope.showDoneButton = true;
            $scope.failureMessage = "There was an issue communicating with the server.";
            notificationsService.error("Server Error", $scope.failureMessage);

        });

    };

    // Cancel.
    $scope.cancel = function () {
        navigationService.hideDialog();
    };

    // Close dialog.
    $scope.closeDialog = function () {
        navigationService.hideDialog();
    };

}

angular.module("umbraco").controller("UGP.SetUserGroupPermissions", SetUserGroupPermissions);<|endoftext|>


<commit_before>/*
 * grunt-dox
 * https://github.com/mattmcmanus/grunt-dox
 *
 * Copyright (c) 2012 Matt McManus
 * Licensed under the MIT license.
 */

var exec = require('child_process').exec,
    fs = require('fs'),
    rimraf = require('rimraf');

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('dox', 'Generate dox output ', function() {

    var filesSrc = grunt.file.expandFiles(this.file.src),
        dest = this.file.dest;
        done = this.async();

    // Cleanup any existing docs
    rimraf.sync(dest);

    // Create a map of
    var files = filesSrc.map(function(file){
      return { src: file, dest: dest + file.replace(/\.js/,".json")}
    })

    grunt.utils.async.forEach( files,
      function dox(file, callback){
        exec('dox < ' + file.src, function(error, stout, sterr){
          grunt.file.write(file.dest, stout);
          grunt.log.writeln('File "' + file.src + '" doxxed.');
          if (!error) callback();
        })
      },
      function(err){
        done();
      })
  });
};
<commit_msg>Combined it all into a single file<commit_after>/*
 * grunt-dox
 * https://github.com/mattmcmanus/grunt-dox
 *
 * Copyright (c) 2012 Matt McManus
 * Licensed under the MIT license.
 */

var exec = require('child_process').exec,
    fs = require('fs'),
    rimraf = require('rimraf');

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('dox', 'Generate dox output ', function() {

    var files = grunt.file.expandFiles(this.file.src),
        dest = this.file.dest;
        done = this.async();

    // Cleanup any existing docs
    rimraf.sync(dest);

    exec('cat ' + files.join(' ') + ' | dox | dox-template', function(error, stout, sterr){
      grunt.file.write(dest + 'index.html', stout);
      grunt.log.writeln('Files "' + files.join(' ') + '" doxxed.');
      if (!error) done();
    })
  });

};
<|endoftext|>


<commit_before>/*
 * grunt-pot
 * https://github.com/stephenharris/grunt-potW
 *
 * Copyright (c) 2013 Stephen Harris
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  grunt.registerMultiTask('pot', 'Scan files and create a .pot file using xgettext', function() {

	var dest = false, inputFiles = "", headerOptions ="";

	var pkg = grunt.file.readJSON('package.json');

    var options = this.options({
		dest: false,
		overwrite: true,
		keywords: false,
		language: false,
		encoding: false,
		text_domain: 'messages',
		package_version: pkg.version,
		package_name: pkg.name,
		msgid_bugs_address: false,
		omit_header: false,
		copyright_holder: false,
		comment_tag: '/'
	});

	grunt.verbose.writeflags(options, 'Pot options');

	//If destination is a directory, build a file based on text domain
	if( options.dest && detectDestType(options.dest) === 'directory' ) {
		options.dest = options.dest.replace(/\/$/, "") + "/"+options.text_domain+".pot";
        }

	if( !grunt.file.exists(options.dest) ){
        grunt.file.write(options.dest);
    }

	grunt.log.writeln('Destination: ' + options.dest);

	//Set join mode
	var join = ( !options.overwrite ? " --join-existing" : "" );

	//Implode keywards
	var keywords = ( options.keywords ? " --keyword=" + options.keywords.join( " --keyword=" ) : "" );

	//Set input files language, if specified
	var language = ( options.language ? " --language="+options.language : "" );

	//Set input files encoding, if required
	var encoding = ( options.encoding ? " --from-code="+options.encoding : "" );

	//Generate header
	if( options.package_version ){
		headerOptions += " --package-version="+options.package_version;
	}

	if( options.package_name ){
		headerOptions += " --package-name="+options.package_name;
	}

	if( options.msgid_bugs_address ){
		headerOptions += " --msgid-bugs-address="+ options.msgid_bugs_address;
	}

	if( options.omit_header ){
		headerOptions += " --omit-header";
	}

	if( options.copyright_holder ){
		headerOptions += " --copyright-holder='"+options.copyright_holder+"'";
	}

	if( options.comment_tag ){
		headerOptions += " --add-comments='"+options.comment_tag+"'";
	}

	//Generate list of files to scan
	this.files.forEach(function(file) {
		inputFiles +=  " " + file.src[0];
	});

	//Compile and run command
	var exec = require('child_process').exec;
	var command = 'xgettext' + join + ' --default-domain=' + options.text_domain + ' -o '+options.dest + language + encoding + keywords + headerOptions + inputFiles;
	var done = grunt.task.current.async();

	grunt.verbose.writeln('Executing: ' + command);

	exec( command,
		function(error, stdout, stderr){
			grunt.verbose.writeln('stderr: ' + stderr);
			done(error); //error will be null if command executed without errors.
		}
  	);

  });

  var detectDestType = function(dest) {
    if (grunt.util._.endsWith(dest, '/')) {
      return 'directory';
    } else {
      return 'file';
    }
  };

};
<commit_msg>Don't overwrite options.dest - instead use potFile variable.<commit_after>/*
 * grunt-pot
 * https://github.com/stephenharris/grunt-potW
 *
 * Copyright (c) 2013 Stephen Harris
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  grunt.registerMultiTask('pot', 'Scan files and create a .pot file using xgettext', function() {

	var dest = false, inputFiles = "", headerOptions ="";

	var pkg = grunt.file.readJSON('package.json');

    var options = this.options({
		dest: false,
		overwrite: true,
		keywords: false,
		language: false,
		encoding: false,
		text_domain: 'messages',
		package_version: pkg.version,
		package_name: pkg.name,
		msgid_bugs_address: false,
		omit_header: false,
		copyright_holder: false,
		comment_tag: '/'
	});

	grunt.verbose.writeflags(options, 'Pot options');

	var potFile = options.dest;
	//If destination is a directory, build a file based on text domain
	if( options.dest && detectDestType(options.dest) === 'directory' ) {
		potFile = options.dest.replace(/\/$/, "") + "/"+options.text_domain+".pot";
        }

	if( !grunt.file.exists(potFile) ){
		grunt.file.write(potFile);
	}

	grunt.log.writeln('Destination: ' + potFile);

	//Set join mode
	var join = ( !options.overwrite ? " --join-existing" : "" );

	//Implode keywards
	var keywords = ( options.keywords ? " --keyword=" + options.keywords.join( " --keyword=" ) : "" );

	//Set input files language, if specified
	var language = ( options.language ? " --language="+options.language : "" );

	//Set input files encoding, if required
	var encoding = ( options.encoding ? " --from-code="+options.encoding : "" );

	//Generate header
	if( options.package_version ){
		headerOptions += " --package-version="+options.package_version;
	}

	if( options.package_name ){
		headerOptions += " --package-name="+options.package_name;
	}

	if( options.msgid_bugs_address ){
		headerOptions += " --msgid-bugs-address="+ options.msgid_bugs_address;
	}

	if( options.omit_header ){
		headerOptions += " --omit-header";
	}

	if( options.copyright_holder ){
		headerOptions += " --copyright-holder='"+options.copyright_holder+"'";
	}

	if( options.comment_tag ){
		headerOptions += " --add-comments='"+options.comment_tag+"'";
	}

	//Generate list of files to scan
	this.files.forEach(function(file) {
		inputFiles +=  " " + file.src[0];
	});

	//Compile and run command
	var exec = require('child_process').exec;
	var command = 'xgettext' + join + ' --default-domain=' + options.text_domain + ' -o '+potFile + language + encoding + keywords + headerOptions + inputFiles;
	var done = grunt.task.current.async();

	grunt.verbose.writeln('Executing: ' + command);

	exec( command,
		function(error, stdout, stderr){
			grunt.verbose.writeln('stderr: ' + stderr);
			done(error); //error will be null if command executed without errors.
		}
  	);

  });

  var detectDestType = function(dest) {
    if (grunt.util._.endsWith(dest, '/')) {
      return 'directory';
    } else {
      return 'file';
    }
  };

};
<|endoftext|>