<commit_before>function log(msg) {
  $('#log').append('

').append(document.createTextNode(msg));
}

$(document).ready(function () {
  var xmpp = new Lightstring.Connection('ws://localhost:5280');
  xmpp.load('DIGEST-MD5', 'presence', 'im', 'roster');

  xmpp.on('connecting', function(stanza) {
    log('connecting')
  });

  xmpp.on('message', function(stanza) {
    var body = stanza.getChild('body');
    if (body) {
      body = body.text();
      log(stanza.attrs.from + ' : ' + body);
      var reply = Lightstring.stanzas.im.chat(stanza.attrs.from, body);
      xmpp.send(reply);
    }
  });

  xmpp.on('connected', function(stanza) {
    log('connected');
    xmpp.presence.send();
      xmpp.roster.get(null, function(stanza) {
        var n = stanza.roster.contacts.length;
        var contact;
        for (var i = 0; i < n; i++) {
          contact = stanza.roster.contacts[i];
          $('#contacts ul').append('
' + contact.jid + '
');
        }
      });
  });

  var oldEmit = xmpp.emit;
  xmpp.emit = function() {
    console.log(arguments);
    oldEmit.apply(xmpp, arguments);
  }

  $('form').submit(function() {
    var jid = $('#jid').val();
    var pass = $('#pass').val();
    xmpp.connect(jid, pass);
    return false;
  });
});

<commit_msg>Make a contact clickable when present<commit_after>function log(msg) {
  $('#log').append('

').append(document.createTextNode(msg));
}

$(document).ready(function () {
  var xmpp = new Lightstring.Connection('ws://localhost:5280');
  xmpp.load('DIGEST-MD5', 'presence', 'im', 'roster');

  xmpp.on('connecting', function(stanza) {
    log('connecting')
  });

  xmpp.on('message', function(stanza) {
    var body = stanza.getChild('body');
    if (body) {
      body = body.text();
      log(stanza.attrs.from + ' : ' + body);
      var reply = Lightstring.stanzas.im.chat(stanza.attrs.from, body);
      xmpp.send(reply);
    }
  });

  xmpp.on('presence', function(stanza) {
    if (stanza.attrs.type)
        return;

    var jid = new Lightstring.JID(stanza.attrs.from).toBare().toString();
    var link = $('' + jid + '').click(function() {});
    $('#contacts ul li[data-jid="' + jid.toString() + '"]').html(link);
  });

  xmpp.on('connected', function(stanza) {
    log('connected');
    xmpp.roster.get(null, function(stanza) {
      var n = stanza.roster.contacts.length;
      for (var i = 0; i < n; i++) {
        var contact = stanza.roster.contacts[i];
        var jid = new Lightstring.JID(contact.jid).toBare();
        $('#contacts ul')
          .append('
' +
                    jid.toString() +
                  '
');
      }
      xmpp.presence.send();
    });
  });

  var oldEmit = xmpp.emit;
  xmpp.emit = function() {
    console.log(arguments);
    oldEmit.apply(xmpp, arguments);
  }

  $('form').submit(function() {
    var jid = $('#jid').val();
    var pass = $('#pass').val();
    xmpp.connect(jid, pass);
    return false;
  });
});

<|endoftext|>


<commit_before>// Default production config

var entry = './app/app.js';

module.exports = [
  // client
  {
    entry: entry,
    longTermCaching: true,
    separateStylesheet: true,
    minimize: true,
    devtool: 'source-map',
    target: 'client'
    // commonsChunk: true
  },

  // server
  {
    entry: entry,
    target: 'node'
  }
];<commit_msg>split out isomorphic, just do one bundle for build<commit_after>// Default production config

module.exports = {
  entry: './app/app.js',
  longTermCaching: true,
  separateStylesheet: true,
  minimize: true,
  devtool: 'source-map',
  target: 'client'
  // commonsChunk: true
};<|endoftext|>


<commit_before>import Ember from 'ember';

export {
    formComponent,
    godForm,
}

let injectStore = Ember.Object.create({
    injectStore: function() {
        if (Ember.isEmpty(this.get('store'))) {
            this.set('store', Ember.inject.service('store'));
        }
    }.on('init')
});

// when godForm call delete, pass selectedItem to success
let deleteObject = function (selectedItem){
    this.toggleProperty('loading');
    this.get('store').deleteRecord(this.get('modelName'), selectedItem).then(Ember.run.bind(this, function(data) {
        this.toggleProperty('loading');
        this.send('success', 'delete', data, selectedItem);
    }), Ember.run.bind(this, function(reason) {
        this.toggleProperty('loading');
        this.send('fail', 'delete', reason, selectedItem);
    }));
};

// godForm mixin is used to controll many object's removing and adding and editing
let godForm = Ember.Mixin.create(injectStore, {
    modelName: '',
    model: null,
    selectedItem: null,
    modalShow: false,
    actions: {
        /**
         * @function add create new record according to modelName
         * @returns  void
         */
        add() {
            this.toggleProperty('modalShow');
            this.set('selectedItem', this.get('store').createRecord(this.get('modelName')));
        },
        /**
         * @function edit triggle when user click edit action
         * @returns  void
         */
        edit(selectedItem) {
            this.toggleProperty('modalShow');
            if (!Ember.isEmpty(selectedItem)) {
                this.set('selectedItem', selectedItem);
            }
        },
        cancel(){
            this.toggleProperty('modalShow');
        },
        remove(selectedItem){
            deleteObject.call(this, selectedItem);
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        success(action, data, selectedItem) {
            this.toggleProperty('modalShow');
            Ember.Logger.info('subclass override this function for response data');
            this.sendAction ? this.sendAction('success', action, data, selectedItem) : '';
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        fail(action, reason, selectedItem) {
            Ember.Logger.info('subclass override this function for fail request');
            this.sendAction ? this.sendAction('fail', action, reason, selectedItem) : '';
        },
    },

});

let formComponent = Ember.Mixin.create(injectStore, {
    modelName: '',
    model: null,
    actions: {
        /**
         * @function save triggle when user click save action
         * @returns  void
         */
        save() {
            this.toggleProperty('loading');
            if (!this.validate()) return;
            this.get('store').save(this.get('modelName'), this.get('model')).then(Ember.run.bind(this, function(data) {
                this.toggleProperty('loading');
                this.send('success', 'save', data);
            }), Ember.run.bind(this, function(reason) {
                this.toggleProperty('loading');
                this.send('fail', 'save', reason);
            }));
        },

        /**
         * @function delete triggle when user click save action
         * @returns  void
         */
        remove() {
            deleteObject.call(this, this.get('model'));
        },

        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        success(action, data) {
            Ember.Logger.info('subclass override this function for response data');
            this.sendAction('success', action, data, this.get('model'));
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        fail(action, reason) {
            Ember.Logger.info('subclass override this function for fail request');
            this.sendAction('fail', action, reason, this.get('model'));
        },
        /**
         * @function validate validate model
         * @returns  Boolean
         */
        cancel() {
            Ember.Logger.info('subclass override this function for form modify cancel');
            this.sendAction('cancel', this.get('model'));
        },
    },
    validate: function() {
        Ember.Logger.info('subclass override this function for model validate');
        return true
    },
});
<commit_msg>fix #10<commit_after>import Ember from 'ember';

export {
    formComponent,
    godForm,
}

let injectStore = Ember.Object.create({
    injectStore: function() {
        if (Ember.isEmpty(this.get('store'))) {
            this.set('store', Ember.inject.service('store'));
        }
    }.on('init')
});

// when godForm call delete, pass selectedItem to success
let deleteObject = function (selectedItem){
    this.toggleProperty('loading');
    this.get('store').deleteRecord(this.get('modelName'), selectedItem).then(Ember.run.bind(this, function(data) {
        this.toggleProperty('loading');
        this.send('success', 'delete', data, selectedItem);
    }), Ember.run.bind(this, function(reason) {
        this.toggleProperty('loading');
        this.send('fail', 'delete', reason, selectedItem);
    }));
};

// godForm mixin is used to controll many object's removing and adding and editing
let godForm = Ember.Mixin.create(injectStore, {
    modelName: '',
    model: null,
    selectedItem: null,
    modalShow: false,
    actions: {
        /**
         * @function add create new record according to modelName
         * @returns  void
         */
        add() {
            this.toggleProperty('modalShow');
            this.set('selectedItem', this.get('store').createRecord(this.get('modelName')));
        },
        /**
         * @function edit triggle when user click edit action
         * @returns  void
         */
        edit(selectedItem) {
            this.toggleProperty('modalShow');
            if (!Ember.isNone(selectedItem)) {
                this.set('selectedItem', selectedItem);
            }
        },
        cancel(){
            this.toggleProperty('modalShow');
        },
        remove(selectedItem){
            deleteObject.call(this, selectedItem);
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        success(action, data, selectedItem) {
            this.toggleProperty('modalShow');
            Ember.Logger.info('subclass override this function for response data');
            this.sendAction ? this.sendAction('success', action, data, selectedItem) : '';
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        fail(action, reason, selectedItem) {
            Ember.Logger.info('subclass override this function for fail request');
            this.sendAction ? this.sendAction('fail', action, reason, selectedItem) : '';
        },
    },

});

let formComponent = Ember.Mixin.create(injectStore, {
    modelName: '',
    model: null,
    actions: {
        /**
         * @function save triggle when user click save action
         * @returns  void
         */
        save() {
            this.toggleProperty('loading');
            if (!this.validate()) return;
            this.get('store').save(this.get('modelName'), this.get('model')).then(Ember.run.bind(this, function(data) {
                this.toggleProperty('loading');
                this.send('success', 'save', data);
            }), Ember.run.bind(this, function(reason) {
                this.toggleProperty('loading');
                this.send('fail', 'save', reason);
            }));
        },

        /**
         * @function delete triggle when user click save action
         * @returns  void
         */
        remove() {
            deleteObject.call(this, this.get('model'));
        },

        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        success(action, data) {
            Ember.Logger.info('subclass override this function for response data');
            this.sendAction('success', action, data, this.get('model'));
        },
        /**
         * @function  success ajax request success callback
         * @returns  void
         */
        fail(action, reason) {
            Ember.Logger.info('subclass override this function for fail request');
            this.sendAction('fail', action, reason, this.get('model'));
        },
        /**
         * @function validate validate model
         * @returns  Boolean
         */
        cancel() {
            Ember.Logger.info('subclass override this function for form modify cancel');
            this.sendAction('cancel', this.get('model'));
        },
    },
    validate: function() {
        Ember.Logger.info('subclass override this function for model validate');
        return true
    },
});
<|endoftext|>


<commit_before>/* global Primus */

var socket = new Primus();

function joinRoom(roomName) {
  return socket.write({type:'joinRoom', room: roomName});
}

function createMessage(message) {
  return socket.write({type:'createMessage', message: message});
}

var messageArea = document.getElementById('messages');

function deliverMessage(message){
  var messageCard = document.createElement('div');
  var messageAuthor = document.createElement('span');
  messageAuthor.className = 'msg-author';
  messageAuthor.textContent = message.author;
  messageCard.appendChild(messageAuthor);
  var messageBody = document.createElement('span');
  messageBody.className = 'msg-body';
  messageBody.textContent = message.body;
  messageCard.appendChild(messageBody);
  messageCard.appendChild(document.createTextNode(' '));

  var follow = messageArea.scrollHeight ==
    messageArea.scrollTop + messageArea.clientHeight;
  messageArea.appendChild(messageCard);
  if (follow) messageArea.scrollTop = messageArea.scrollHeight;
}

var roomInput = document.getElementById('roominput');
var msgForm = document.getElementById('entrybox');
var msgInput = document.getElementById('msginput');
var nameInput = document.getElementById('nameinput');

roomInput.addEventListener('input', function setAdHocFilter() {
  var card = messageArea.lastChild;
  while (card) {
    messageArea.removeChild(card);
    card = messageArea.lastChild;
  }
  joinRoom(roomInput.value);
});

msgForm.addEventListener('submit', function sendMessage(evt){
  createMessage({
    body: msgInput.value,
    author: nameInput.value
  });
  msgInput.value = '';
  return evt.preventDefault();
});

socket.on("data", function(data) {
  if (data.type == 'error') return console.error(data);
  else if (data.type == 'deliverMessage') {
    return deliverMessage(data.message);
  } else {
    console.error('Unrecognized message type', data);
  }
});
<commit_msg>Fix room not being included in send, add lobby join<commit_after>/* global Primus */

var socket = new Primus();

function joinRoom(roomName) {
  return socket.write({type:'joinRoom', room: roomName});
}

function createMessage(message) {
  return socket.write({type:'createMessage', message: message});
}

var messageArea = document.getElementById('messages');

function deliverMessage(message){
  var messageCard = document.createElement('div');
  var messageAuthor = document.createElement('span');
  messageAuthor.className = 'msg-author';
  messageAuthor.textContent = message.author;
  messageCard.appendChild(messageAuthor);
  var messageBody = document.createElement('span');
  messageBody.className = 'msg-body';
  messageBody.textContent = message.body;
  messageCard.appendChild(messageBody);
  messageCard.appendChild(document.createTextNode(' '));

  var follow = messageArea.scrollHeight ==
    messageArea.scrollTop + messageArea.clientHeight;
  messageArea.appendChild(messageCard);
  if (follow) messageArea.scrollTop = messageArea.scrollHeight;
}

var roomInput = document.getElementById('roominput');
var msgForm = document.getElementById('entrybox');
var msgInput = document.getElementById('msginput');
var nameInput = document.getElementById('nameinput');

roomInput.addEventListener('input', function setAdHocFilter() {
  var card = messageArea.lastChild;
  while (card) {
    messageArea.removeChild(card);
    card = messageArea.lastChild;
  }
  joinRoom(roomInput.value);
});

msgForm.addEventListener('submit', function sendMessage(evt){
  createMessage({
    body: msgInput.value,
    room: roomInput.value,
    author: nameInput.value
  });
  msgInput.value = '';
  return evt.preventDefault();
});

socket.on("data", function(data) {
  if (data.type == 'error') return console.error(data);
  else if (data.type == 'deliverMessage') {
    return deliverMessage(data.message);
  } else {
    console.error('Unrecognized message type', data);
  }
});

// start out in the "lobby"
joinRoom('');
<|endoftext|>


<commit_before>/*
  this module is intended to contain all uses of Ember and Ember Data
  private APIs that are needed to make this addon function
*/

import Ember from 'ember';
import normalizeModelName from "ember-data/-private/system/normalize-model-name";
import { singularize } from 'ember-inflector';

export function lookupIdentityKey(store, type, id) {
  return store._internalModelForId(singularize(normalizeModelName(type)), id);
}

export function extractIdentityKey(model) {
  return model._internalModel;
}

// WeakMap is in here because Ember contains a WeakMap polyfill we can
// use, but it's not exposed by public API.
export let WeakMap;
if (window.WeakMap) {
  WeakMap = window.WeakMap;
} else {
  WeakMap = Ember.__loader.require('ember-metal/weak_map').default;
}
<commit_msg>update to match newer ember's feature flagging infrastructure<commit_after>/*
  this module is intended to contain all uses of Ember and Ember Data
  private APIs that are needed to make this addon function
*/

import Ember from 'ember';
import normalizeModelName from "ember-data/-private/system/normalize-model-name";
import { singularize } from 'ember-inflector';

export function lookupIdentityKey(store, type, id) {
  return store._internalModelForId(singularize(normalizeModelName(type)), id);
}

export function extractIdentityKey(model) {
  return model._internalModel;
}

// WeakMap is in here because Ember contains a WeakMap polyfill we can
// use, but it's not exposed by public API.
export let WeakMap;
if (window.WeakMap) {
  WeakMap = window.WeakMap;
} else {
  let metal = Ember.__loader.require('ember-metal');
  if (metal.WeakMap) {
    WeakMap = metal.WeakMap;
  } else {
    WeakMap = Ember.__loader.require('ember-metal/weak_map').default;
  }
}
<|endoftext|>


<commit_before>define(function (require) {
    "use strict";
    var CodeMirror = require('codemirror');
    var _ = require('underscore');
    var colour = require('colour');
    var Toggles = require('toggles');
    var compiler = require('compiler');
    var loadSaveLib = require('loadSave');

    require('codemirror/mode/clike/clike');
    require('codemirror/mode/d/d');
    require('codemirror/mode/go/go');
    require('codemirror/mode/rust/rust');

    var loadSave = new loadSaveLib.LoadSave();

    function Editor(hub, state, container, lang, defaultSrc) {
        var self = this;
        this.id = state.id || hub.nextId();
        this.container = container;
        this.domRoot = container.getElement();
        this.domRoot.html($('#codeEditor').html());
        this.eventHub = hub.createEventHub();

        this.widgetsByCompiler = {};
        this.asmByCompiler = {};
        this.options = new Toggles(this.domRoot.find('.options'), state.options);
        this.options.on('change', _.bind(this.onOptionsChange, this));

        var cmMode;
        switch (lang.toLowerCase()) {
            default:
                cmMode = "text/x-c++src";
                break;
            case "c":
                cmMode = "text/x-c";
                break;
            case "rust":
                cmMode = "text/x-rustsrc";
                break;
            case "d":
                cmMode = "text/x-d";
                break;
            case "go":
                cmMode = "text/x-go";
                break;
        }

        this.editor = CodeMirror.fromTextArea(this.domRoot.find("textarea")[0], {
            lineNumbers: true,
            matchBrackets: true,
            useCPP: true,
            mode: cmMode
        });

        if (state.src) {
            this.editor.setValue(state.src);
        } else if (defaultSrc) {
            this.editor.setValue(defaultSrc);
        }

        // With reference to "fix typing '#' in emacs mode"
        // https://github.com/mattgodbolt/gcc-explorer/pull/131
        this.editor.setOption("extraKeys", {
            "Alt-F": false
        });

        // We suppress posting changes until the user has stopped typing by:
        // * Using _.debounce() to run emitChange on any key event or change
        //   only after a delay.
        // * Only actually triggering a change if the document text has changed from
        //   the previous emitted.
        this.lastChangeEmitted = null;
        var ChangeDebounceMs = 500;
        this.debouncedEmitChange = _.debounce(function () {
            if (self.options.get().compileOnChange) self.maybeEmitChange();
        }, ChangeDebounceMs);
        this.editor.on("change", _.bind(function () {
            this.debouncedEmitChange();
            this.updateState();
        }, this));
        this.editor.on("keydown", _.bind(function () {
            // Not strictly a change; but this suppresses changes until some time
            // after the last key down (be it an actual change or a just a cursor
            // movement etc).
            this.debouncedEmitChange();
        }, this));

        // A small debounce used to give multiple compilers a chance to respond
        // before unioning the colours and updating them. Another approach to reducing
        // flicker as multiple compilers update is to track those compilers which
        // are busy, and only union/update colours when all are complete.
        var ColourDebounceMs = 200;
        this.debouncedUpdateColours = _.debounce(function (colours) {
            self.updateColours(colours);
        }, ColourDebounceMs);

        function resize() {
            var topBarHeight = self.domRoot.find(".top-bar").outerHeight(true);
            self.editor.setSize(self.domRoot.width(), self.domRoot.height() - topBarHeight);
            self.editor.refresh();
        }

        this.domRoot.find('.load-save').click(_.bind(function () {
            loadSave.run(_.bind(function (text) {
                this.editor.setValue(text);
                this.maybeEmitChange();
            }, this));
        }, this));

        container.on('resize', resize);
        container.on('open', function () {
            self.eventHub.emit('editorOpen', self.id);
        });
        container.on('destroy', function () {
            self.eventHub.unsubscribe();
            self.eventHub.emit('editorClose', self.id);
        });
        container.setTitle(lang + " source #" + self.id);
        this.container.layoutManager.on('initialised', function () {
            // Once initialized, let everyone know what text we have.
            self.maybeEmitChange();
        });

        this.eventHub.on('compilerOpen', this.onCompilerOpen, this);
        this.eventHub.on('compilerClose', this.onCompilerClose, this);
        this.eventHub.on('compileResult', this.onCompileResponse, this);

        var compilerConfig = compiler.getComponent(this.id);
        this.container.layoutManager.createDragSource(
            this.domRoot.find('.btn.add-compiler'), compilerConfig);
    }

    Editor.prototype.maybeEmitChange = function (force) {
        var source = this.getSource();
        if (!force && source == this.lastChangeEmitted) return;
        this.lastChangeEmitted = this.getSource();
        this.eventHub.emit('editorChange', this.id, this.lastChangeEmitted);
    };

    Editor.prototype.updateState = function () {
        this.container.setState({
            id: this.id,
            src: this.getSource(),
            options: this.options.get()
        });
    };

    Editor.prototype.getSource = function () {
        return this.editor.getValue();
    };

    Editor.prototype.onOptionsChange = function (before, after) {
        this.updateState();
        // TODO: bug with options and filters: initial click seems to get lost!
        // TODO: bug when:
        // * Turn off auto.
        // * edit code
        // * change compiler or compiler options (out of date code is used)
        if (after.compileOnChange && !before.compileOnChange) {
            // If we've just enabled "compile on change"; forcibly send a change
            // which will recolourise as required.
            this.maybeEmitChange(true);
        } else if (before.colouriseAsm !== after.colouriseAsm) {
            // if the colourise option has been toggled...recompute colours
            this.numberUsedLines();
        }
    };

    function makeErrorNode(text, compiler) {
        var clazz = "error";
        if (text.match(/^warning/)) clazz = "warning";
        if (text.match(/^note/)) clazz = "note";
        var node = $('
!!:
');
        node.find(".msg").text(text);
        node.find(".compiler").text(compiler);
        return node[0];
    }

    function parseLines(lines, callback) {
        var re = /^\/tmp\/[^:]+:([0-9]+)(:([0-9]+))?:\s+(.*)/;
        $.each(lines.split('\n'), function (_, line) {
            line = line.trim();
            if (line !== "") {
                var match = line.match(re);
                if (match) {
                    callback(parseInt(match[1]), match[4].trim());
                } else {
                    callback(null, line);
                }
            }
        });
    }

    Editor.prototype.removeWidgets = function (widgets) {
        var self = this;
        _.each(widgets, function (widget) {
            self.editor.removeLineWidget(widget);
        });
    };

    Editor.prototype.numberUsedLines = function () {
        var result = {};
        // First, note all lines used.
        _.each(this.asmByCompiler, function (asm) {
            _.each(asm, function (asmLine) {
                if (asmLine.source) result[asmLine.source - 1] = true;
            });
        });
        // Now assign an ordinal to each used line.
        var ordinal = 0;
        _.each(result, function (v, k) {
            result[k] = ordinal++;
        });

        this.debouncedUpdateColours(this.options.get().colouriseAsm ? result : []);
    };

    Editor.prototype.updateColours = function (colours) {
        colour.applyColours(this.editor, colours);
        this.eventHub.emit('colours', this.id, colours);
    };

    Editor.prototype.onCompilerClose = function (compilerId) {
        this.removeWidgets(this.widgetsByCompiler[compilerId]);
        delete this.widgetsByCompiler[compilerId];
        delete this.asmByCompiler[compilerId];
        this.numberUsedLines();
    };

    Editor.prototype.onCompilerOpen = function () {
        // On any compiler open, rebroadcast our state in case they need to know it.
        this.maybeEmitChange(true);
    };

    Editor.prototype.onCompileResponse = function (compilerId, compiler, result) {
        var output = (result.stdout || "") + (result.stderr || "");
        var self = this;
        this.removeWidgets(this.widgetsByCompiler[compilerId]);
        var widgets = [];
        parseLines(output, function (lineNum, msg) {
            if (lineNum) {
                var widget = self.editor.addLineWidget(
                    lineNum - 1,
                    makeErrorNode(msg, compiler.name),
                    {coverGutter: false, noHScroll: true});
                widgets.push(widget);
            }
        });
        this.widgetsByCompiler[compilerId] = widgets;
        this.asmByCompiler[compilerId] = result.asm;
        this.numberUsedLines();
    };

    return {
        Editor: Editor,
        getComponent: function (id) {
            return {
                type: 'component',
                componentName: 'codeEditor',
                componentState: {id: id},
                isClosable: false
            };
        }
    };
});<commit_msg>Mark a TODO to-done<commit_after>define(function (require) {
    "use strict";
    var CodeMirror = require('codemirror');
    var _ = require('underscore');
    var colour = require('colour');
    var Toggles = require('toggles');
    var compiler = require('compiler');
    var loadSaveLib = require('loadSave');

    require('codemirror/mode/clike/clike');
    require('codemirror/mode/d/d');
    require('codemirror/mode/go/go');
    require('codemirror/mode/rust/rust');

    var loadSave = new loadSaveLib.LoadSave();

    function Editor(hub, state, container, lang, defaultSrc) {
        var self = this;
        this.id = state.id || hub.nextId();
        this.container = container;
        this.domRoot = container.getElement();
        this.domRoot.html($('#codeEditor').html());
        this.eventHub = hub.createEventHub();

        this.widgetsByCompiler = {};
        this.asmByCompiler = {};
        this.options = new Toggles(this.domRoot.find('.options'), state.options);
        this.options.on('change', _.bind(this.onOptionsChange, this));

        var cmMode;
        switch (lang.toLowerCase()) {
            default:
                cmMode = "text/x-c++src";
                break;
            case "c":
                cmMode = "text/x-c";
                break;
            case "rust":
                cmMode = "text/x-rustsrc";
                break;
            case "d":
                cmMode = "text/x-d";
                break;
            case "go":
                cmMode = "text/x-go";
                break;
        }

        this.editor = CodeMirror.fromTextArea(this.domRoot.find("textarea")[0], {
            lineNumbers: true,
            matchBrackets: true,
            useCPP: true,
            mode: cmMode
        });

        if (state.src) {
            this.editor.setValue(state.src);
        } else if (defaultSrc) {
            this.editor.setValue(defaultSrc);
        }

        // With reference to "fix typing '#' in emacs mode"
        // https://github.com/mattgodbolt/gcc-explorer/pull/131
        this.editor.setOption("extraKeys", {
            "Alt-F": false
        });

        // We suppress posting changes until the user has stopped typing by:
        // * Using _.debounce() to run emitChange on any key event or change
        //   only after a delay.
        // * Only actually triggering a change if the document text has changed from
        //   the previous emitted.
        this.lastChangeEmitted = null;
        var ChangeDebounceMs = 500;
        this.debouncedEmitChange = _.debounce(function () {
            if (self.options.get().compileOnChange) self.maybeEmitChange();
        }, ChangeDebounceMs);
        this.editor.on("change", _.bind(function () {
            this.debouncedEmitChange();
            this.updateState();
        }, this));
        this.editor.on("keydown", _.bind(function () {
            // Not strictly a change; but this suppresses changes until some time
            // after the last key down (be it an actual change or a just a cursor
            // movement etc).
            this.debouncedEmitChange();
        }, this));

        // A small debounce used to give multiple compilers a chance to respond
        // before unioning the colours and updating them. Another approach to reducing
        // flicker as multiple compilers update is to track those compilers which
        // are busy, and only union/update colours when all are complete.
        var ColourDebounceMs = 200;
        this.debouncedUpdateColours = _.debounce(function (colours) {
            self.updateColours(colours);
        }, ColourDebounceMs);

        function resize() {
            var topBarHeight = self.domRoot.find(".top-bar").outerHeight(true);
            self.editor.setSize(self.domRoot.width(), self.domRoot.height() - topBarHeight);
            self.editor.refresh();
        }

        this.domRoot.find('.load-save').click(_.bind(function () {
            loadSave.run(_.bind(function (text) {
                this.editor.setValue(text);
                this.maybeEmitChange();
            }, this));
        }, this));

        container.on('resize', resize);
        container.on('open', function () {
            self.eventHub.emit('editorOpen', self.id);
        });
        container.on('destroy', function () {
            self.eventHub.unsubscribe();
            self.eventHub.emit('editorClose', self.id);
        });
        container.setTitle(lang + " source #" + self.id);
        this.container.layoutManager.on('initialised', function () {
            // Once initialized, let everyone know what text we have.
            self.maybeEmitChange();
        });

        this.eventHub.on('compilerOpen', this.onCompilerOpen, this);
        this.eventHub.on('compilerClose', this.onCompilerClose, this);
        this.eventHub.on('compileResult', this.onCompileResponse, this);

        var compilerConfig = compiler.getComponent(this.id);
        this.container.layoutManager.createDragSource(
            this.domRoot.find('.btn.add-compiler'), compilerConfig);
    }

    Editor.prototype.maybeEmitChange = function (force) {
        var source = this.getSource();
        if (!force && source == this.lastChangeEmitted) return;
        this.lastChangeEmitted = this.getSource();
        this.eventHub.emit('editorChange', this.id, this.lastChangeEmitted);
    };

    Editor.prototype.updateState = function () {
        this.container.setState({
            id: this.id,
            src: this.getSource(),
            options: this.options.get()
        });
    };

    Editor.prototype.getSource = function () {
        return this.editor.getValue();
    };

    Editor.prototype.onOptionsChange = function (before, after) {
        this.updateState();
        // TODO: bug when:
        // * Turn off auto.
        // * edit code
        // * change compiler or compiler options (out of date code is used)
        if (after.compileOnChange && !before.compileOnChange) {
            // If we've just enabled "compile on change"; forcibly send a change
            // which will recolourise as required.
            this.maybeEmitChange(true);
        } else if (before.colouriseAsm !== after.colouriseAsm) {
            // if the colourise option has been toggled...recompute colours
            this.numberUsedLines();
        }
    };

    function makeErrorNode(text, compiler) {
        var clazz = "error";
        if (text.match(/^warning/)) clazz = "warning";
        if (text.match(/^note/)) clazz = "note";
        var node = $('
!!:
');
        node.find(".msg").text(text);
        node.find(".compiler").text(compiler);
        return node[0];
    }

    function parseLines(lines, callback) {
        var re = /^\/tmp\/[^:]+:([0-9]+)(:([0-9]+))?:\s+(.*)/;
        $.each(lines.split('\n'), function (_, line) {
            line = line.trim();
            if (line !== "") {
                var match = line.match(re);
                if (match) {
                    callback(parseInt(match[1]), match[4].trim());
                } else {
                    callback(null, line);
                }
            }
        });
    }

    Editor.prototype.removeWidgets = function (widgets) {
        var self = this;
        _.each(widgets, function (widget) {
            self.editor.removeLineWidget(widget);
        });
    };

    Editor.prototype.numberUsedLines = function () {
        var result = {};
        // First, note all lines used.
        _.each(this.asmByCompiler, function (asm) {
            _.each(asm, function (asmLine) {
                if (asmLine.source) result[asmLine.source - 1] = true;
            });
        });
        // Now assign an ordinal to each used line.
        var ordinal = 0;
        _.each(result, function (v, k) {
            result[k] = ordinal++;
        });

        this.debouncedUpdateColours(this.options.get().colouriseAsm ? result : []);
    };

    Editor.prototype.updateColours = function (colours) {
        colour.applyColours(this.editor, colours);
        this.eventHub.emit('colours', this.id, colours);
    };

    Editor.prototype.onCompilerClose = function (compilerId) {
        this.removeWidgets(this.widgetsByCompiler[compilerId]);
        delete this.widgetsByCompiler[compilerId];
        delete this.asmByCompiler[compilerId];
        this.numberUsedLines();
    };

    Editor.prototype.onCompilerOpen = function () {
        // On any compiler open, rebroadcast our state in case they need to know it.
        this.maybeEmitChange(true);
    };

    Editor.prototype.onCompileResponse = function (compilerId, compiler, result) {
        var output = (result.stdout || "") + (result.stderr || "");
        var self = this;
        this.removeWidgets(this.widgetsByCompiler[compilerId]);
        var widgets = [];
        parseLines(output, function (lineNum, msg) {
            if (lineNum) {
                var widget = self.editor.addLineWidget(
                    lineNum - 1,
                    makeErrorNode(msg, compiler.name),
                    {coverGutter: false, noHScroll: true});
                widgets.push(widget);
            }
        });
        this.widgetsByCompiler[compilerId] = widgets;
        this.asmByCompiler[compilerId] = result.asm;
        this.numberUsedLines();
    };

    return {
        Editor: Editor,
        getComponent: function (id) {
            return {
                type: 'component',
                componentName: 'codeEditor',
                componentState: {id: id},
                isClosable: false
            };
        }
    };
});<|endoftext|>


<commit_before>import ChunkBuilder from '../chunk-builder';

const Spawn = {
    getTileData() {
        return ChunkBuilder
            .newEmpty()
            .fillSquare('B03', {
                width: 40,
                height: 20
            })
            .addSimpleHouse(5, 5)
            .addCoast()
            .padWithWater(10)
            .generateChunk();
    },

    playerStartPosition() {
        return {x: 410, y: 965};
    }
};

export default Spawn;
<commit_msg>added some more houses, looks a bit derpy<commit_after>import ChunkBuilder from '../chunk-builder';

const Spawn = {
    getTileData() {
        return ChunkBuilder
            .newEmpty()
            .fillSquare('B03', {
                width: 40,
                height: 20
            })
            .addCoast()
            .addSimpleHouse(0, 5)
            .addSimpleHouse(0, 10)
            .addSimpleHouse(0, 15)
            .addSimpleHouse(0, 20)
            .addSimpleHouse(0, 25)
            .padWithWater(10)
            .generateChunk();
    },

    playerStartPosition() {
        return {x: 410, y: 965};
    }
};

export default Spawn;
<|endoftext|>


<commit_before>$(document).ready(function(){

  //----- VARS -----//

  var lastSearch = ""; //will be value of last search to use when adding related words

  var template = twig({
    id: "headlines",
    href: "templates/ajax-headlines.twig",

     load: function(template) { console.log(template); }
  });

  var wordTemplate = twig({
    id: "related",
    href: "templates/ajax-related.twig",

     load: function(template) { console.log(template); }
  });

  //----- FUNCTIONS -----//

  function getHeadlines(event) {
    event.preventDefault();
    var $input = $('.js-headline-search');
    var searchTerms = $input.val().split(' ').join(',');
    ajaxNews(searchTerms, false);
    ajaxRelated(searchTerms);
  }

  function ajaxNews(terms, test) {
    console.log('terms: ' + terms);
    var url = "search.php?terms=" + terms; //something;

    // send request to server for json of search data
    // promise with callback to parse data

    $.ajax({
      dataType: "json",
      url: url,
      success: test ? testData : parseData
    });

    $('.loading').addClass('is-open');
  }

  function testData (data) {
    console.log('test fired');
    console.log(data);
  }

  function parseData(data) {
    console.log(data);

    for (var i = 0; i < data.length; i +=1) {
      if (data[i].publishedDate) {
        data[i].publishedDate = fixDate(data[i].publishedDate);
      }
    }

    parsedData = data;
    renderHeadlines(parsedData);
  }

  function fixDate(dateToFix) {
    var fixedDate = moment(dateToFix).fromNow();
    console.log (fixedDate);
    return fixedDate;
  }

  function renderHeadlines(parsedData) {

    // render twig template with data
    // send to browser

    // render the template
    var headlinesHTML = twig({ ref: "headlines" }).render({headlines: parsedData});
    $('.loading').removeClass('is-open');

    // Display the rendered template
    $('.headlines-mod').html(headlinesHTML);

  }

  function renderRelated(parsedData) {

    // render twig template with data
    // send to browser

    // render the template
    var headlinesHTML = twig({ ref: "headlines" }).render({headlines: parsedData});

    // Display the rendered template
    $('.headlines-mod').html(headlinesHTML);

  }

  function splitSearch() {
    // get value of search input
    // split value at spaces and store in array
    // foreach element in array render search word in a box in the input.
  }

  function ajaxRelated(terms, test) {
    console.log('terms: ' + terms);
    var url = "related.php?terms=" + terms; //something;

    // send request to server for json of search data
    // promise with callback to parse data

    $.ajax({
      dataType: "json",
      url: url,
      success: renderWordBar
    });
  }

  function renderWordBar(data) {
    var data = data.slice(0, 6);
    var relatedHTML = twig({ ref: "related" }).render({related: data});

    // First clear the related keywords bar
    $('.result-filter-mod').empty();

    // Display 'suggested keywords' helper text
    $('.result-filter-mod').append("
Suggested Keywords
");

    // Display the rendered template
    $('.result-filter-mod').append(relatedHTML);
  }

  function addWord(event) {
    var $target = $(event.target);
    var $input = $('.js-headline-search');
    var wordToAdd = $target.text();
    var $searchTokens = $('#search-term-tokens');

    $input.val(lastSearch + ' ' + wordToAdd);
    $('#search-term-tokens').empty();
    $input.submit();
  }

  //----- LISTENERS -----//

   // Clear tokens on clicking the x
   var deleteToken = function() {
    // superficially delete it
    $('.token-delete').on('click', function() {
      $(this).parent().remove();
    })
  };

  $('.headline-search').on('submit', getHeadlines);
  $('.headline-search').on('submit', function() {
    event.preventDefault();
    var $input = $('.js-headline-search');
    lastSearch = $input.val();
    var searchTerms = $input.val().split(' ');
    var $numberOfSearchTerms = searchTerms.length;

    var insertSearchTermsIntoSearchBar = function() {
      for (var i = 0; i < $numberOfSearchTerms; i++) {
        $('#search-term-tokens').append("
" + searchTerms[i] + "x
");
      }
      // clears search field input
      $('#headline-search-input').val("").removeAttr('placeholder');

    }
    insertSearchTermsIntoSearchBar();
    deleteToken();
  });

  $('.result-filter-mod').on('click', 'li', addWord);

  // Clear the input form (and fake input tokens) on focus
  var clearSearchBar = function() {
    $('#headline-search-input').on('click', function() {
      console.log('focus');
      $(this).val("");
      $('#search-term-tokens').empty();
      //$('.result-filter-mod').empty();
    })
  };

  clearSearchBar();

  // Actually delete it from the search string
  $('.token-delete').on('click', function() {
    console.log('you are deleting something');
    var $wordToDelete = $(this);
    var lastSearch = lastSearch.replace($wordToDelete, "");
    var $input = $('.js-headline-search');
    $input.submit();
    console.log(lastSearch);
  });

  //----- TESTS -----//

//  ajaxNews('cheese,bears,ebola', true);

});
<commit_msg>deleteWord function plz work<commit_after>$(document).ready(function(){

  //----- VARS -----//

  var lastSearch = ""; //will be value of last search to use when adding related words

  var template = twig({
    id: "headlines",
    href: "templates/ajax-headlines.twig",

     load: function(template) { console.log(template); }
  });

  var wordTemplate = twig({
    id: "related",
    href: "templates/ajax-related.twig",

     load: function(template) { console.log(template); }
  });

  //----- FUNCTIONS -----//

  function getHeadlines(event) {
    event.preventDefault();
    var $input = $('.js-headline-search');
    var searchTerms = $input.val().split(' ').join(',');
    ajaxNews(searchTerms, false);
    ajaxRelated(searchTerms);
  }

  function ajaxNews(terms, test) {
    console.log('terms: ' + terms);
    var url = "search.php?terms=" + terms; //something;

    // send request to server for json of search data
    // promise with callback to parse data

    $.ajax({
      dataType: "json",
      url: url,
      success: test ? testData : parseData
    });

    $('.loading').addClass('is-open');
  }

  function testData (data) {
    console.log('test fired');
    console.log(data);
  }

  function parseData(data) {
    console.log(data);

    for (var i = 0; i < data.length; i +=1) {
      if (data[i].publishedDate) {
        data[i].publishedDate = fixDate(data[i].publishedDate);
      }
    }

    parsedData = data;
    renderHeadlines(parsedData);
  }

  function fixDate(dateToFix) {
    var fixedDate = moment(dateToFix).fromNow();
    console.log (fixedDate);
    return fixedDate;
  }

  function renderHeadlines(parsedData) {

    // render twig template with data
    // send to browser

    // render the template
    var headlinesHTML = twig({ ref: "headlines" }).render({headlines: parsedData});
    $('.loading').removeClass('is-open');

    // Display the rendered template
    $('.headlines-mod').html(headlinesHTML);

  }

  function renderRelated(parsedData) {

    // render twig template with data
    // send to browser

    // render the template
    var headlinesHTML = twig({ ref: "headlines" }).render({headlines: parsedData});

    // Display the rendered template
    $('.headlines-mod').html(headlinesHTML);

  }

  function splitSearch() {
    // get value of search input
    // split value at spaces and store in array
    // foreach element in array render search word in a box in the input.
  }

  function ajaxRelated(terms, test) {
    console.log('terms: ' + terms);
    var url = "related.php?terms=" + terms; //something;

    // send request to server for json of search data
    // promise with callback to parse data

    $.ajax({
      dataType: "json",
      url: url,
      success: renderWordBar
    });
  }

  function renderWordBar(data) {
    var data = data.slice(0, 6);
    var relatedHTML = twig({ ref: "related" }).render({related: data});

    // First clear the related keywords bar
    $('.result-filter-mod').empty();

    // Display 'suggested keywords' helper text
    $('.result-filter-mod').append("
Suggested Keywords
");

    // Display the rendered template
    $('.result-filter-mod').append(relatedHTML);
  }

  function addWord(event) {
    var $target = $(event.target);
    var $input = $('.js-headline-search');
    var wordToAdd = $target.text();
    var $searchTokens = $('#search-term-tokens');

    $input.val(lastSearch + ' ' + wordToAdd);
    $('#search-term-tokens').empty();
    $input.submit();
  }

  //----- LISTENERS -----//

   // Clear tokens on clicking the x
   var deleteToken = function() {
    // superficially delete it
    $('.token-delete').on('click', function() {
      $(this).parent().remove();
    });
    }

  $('.headline-search').on('submit', getHeadlines);
  $('.headline-search').on('submit', function() {
    event.preventDefault();
    var $input = $('.js-headline-search');
    lastSearch = $input.val();
    var searchTerms = $input.val().split(' ');
    var $numberOfSearchTerms = searchTerms.length;

    var insertSearchTermsIntoSearchBar = function() {
      for (var i = 0; i < $numberOfSearchTerms; i++) {
        $('#search-term-tokens').append("
" + searchTerms[i] + "x
");
      }
      // clears search field input
      $('#headline-search-input').val("").removeAttr('placeholder');

    }
    insertSearchTermsIntoSearchBar();
    deleteToken();
  });

  $('.result-filter-mod').on('click', 'li', addWord);

  // Clear the input form (and fake input tokens) on focus
  var clearSearchBar = function() {
    $('#headline-search-input').on('click', function() {
      console.log('focus');
      $(this).val("");
      $('#search-term-tokens').empty();
      //$('.result-filter-mod').empty();
    })
  };

  clearSearchBar();

  // Actually delete it
  $('.token-delete').on('click', function() {
      var $wordToDelete = $(this).parent().text();
      lastSearch = lastSearch.replace($wordToDelete, "");
      var $input = $('.js-headline-search');
      $input.submit();
      console.log(lastSearch);
  });

  //----- TESTS -----//

//  ajaxNews('cheese,bears,ebola', true);

});
<|endoftext|>


<commit_before>'use strict';

var EditorState = {
    CLEAN: 0, // NO CHANGES
    DIRTY: 1, // UNSAVED CHANGES
    SAVE: 2, // SAVE IN PROGRESS
    LOAD: 3, // LOADING
    READONLY: 4
};

var Actions = {
    LOAD: "load",
    CREATE: "create"
};

//first, checks if it isn't implemented yet
if (!String.prototype.format) {
    String.prototype.format = function () {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined'
                ? args[number]
                : match
                ;
        });
    };
}

google.load('picker', '1');
gapi.load('drive-share');

angular.module('app', ['app.controllers', 'app.filters', 'app.services', 'app.directives', 'ui.keypress', 'ui.bootstrap', 'analytics'])
    .constant('appName', 'VideoNot.es')
    .constant('saveInterval', 15000)
    .constant('sampleVideo', 'http://www.youtube.com/watch?v=U6FvJ6jMGHU') // Please replace this with your Application ID.
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/', {templateUrl: '/partials/home.html', controller: "HomeCtrl"})
            .when('/edit/', {templateUrl: '/partials/editor.html', controller: 'MainCtrl', action: Actions.CREATE})
            .when('/edit/:id', {templateUrl: '/partials/editor.html', controller: 'MainCtrl', action: Actions.LOAD})
            .otherwise({redirectTo: '/'});
    }])
    .config(['$tooltipProvider', function ($tooltipProvider) {
        $tooltipProvider.options( { appendToBody: true } );
    }])
    .run(['$rootScope', function ($rootScope) {
        // Many events binding
        $rootScope.$onMany = function (events, fn) {
            for (var i = 0; i < events.length; i++) {
                this.$on(events[i], fn);
            }
        };
    }])
    // Error handler
    .run(['$window', 'analytics', function ($window, analytics) {
        $window.onerror = function(message, url, line) {
            analytics.pushAnalytics([
                "_trackEvent",
                "JS Exception Error",
                message,
                (url + " (" + line + ")"),
                0, true
            ]);
        };
    }]);
<commit_msg>safeApply<commit_after>'use strict';

var EditorState = {
    CLEAN: 0, // NO CHANGES
    DIRTY: 1, // UNSAVED CHANGES
    SAVE: 2, // SAVE IN PROGRESS
    LOAD: 3, // LOADING
    READONLY: 4
};

var Actions = {
    LOAD: "load",
    CREATE: "create"
};

//first, checks if it isn't implemented yet
if (!String.prototype.format) {
    String.prototype.format = function () {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined'
                ? args[number]
                : match
                ;
        });
    };
}

google.load('picker', '1');
gapi.load('drive-share');

angular.module('app', ['app.controllers', 'app.filters', 'app.services', 'app.directives', 'ui.keypress', 'ui.bootstrap', 'analytics'])
    .constant('appName', 'VideoNot.es')
    .constant('saveInterval', 15000)
    .constant('sampleVideo', 'http://www.youtube.com/watch?v=U6FvJ6jMGHU') // Please replace this with your Application ID.
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/', {templateUrl: '/partials/home.html', controller: "HomeCtrl"})
            .when('/edit/', {templateUrl: '/partials/editor.html', controller: 'MainCtrl', action: Actions.CREATE})
            .when('/edit/:id', {templateUrl: '/partials/editor.html', controller: 'MainCtrl', action: Actions.LOAD})
            .otherwise({redirectTo: '/'});
    }])
    .config(['$tooltipProvider', function ($tooltipProvider) {
        $tooltipProvider.options( { appendToBody: true } );
    }])
    .run(['$rootScope', function ($rootScope) {
        // Many events binding
        $rootScope.$onMany = function (events, fn) {
            for (var i = 0; i < events.length; i++) {
                this.$on(events[i], fn);
            }
        };

        $rootScope.safeApply = function(fn) {
            var phase = this.$root.$$phase;
            if(phase == '$apply' || phase == '$digest') {
                if(fn && (typeof(fn) === 'function')) {
                    fn();
                }
            } else {
                this.$apply(fn);
            }
        };
    }])
    // Error handler
    .run(['$window', 'analytics', function ($window, analytics) {
        $window.onerror = function(message, url, line) {
            analytics.pushAnalytics([
                "_trackEvent",
                "JS Exception Error",
                message,
                (url + " (" + line + ")"),
                0, true
            ]);
        };
    }]);
<|endoftext|>


<commit_before>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication');
const errors = require('feathers-errors');

const filterApplicableSubmissions = hook => {
    let data = hook.result.data || hook.result;
    if (hook.params.account) {
        Promise.all(data.filter(function(e) {
            let c = JSON.parse(JSON.stringify(e));
            if (typeof c.teamMembers[0] === 'object') {
                c.teamMembers = c.teamMembers.map(e => { return e._id; }); // map teamMembers list to _id list (if $populate(d) is used)
            }

            let promise;
            if (typeof c.courseGroupId === 'object') {
                promise = Promise.resolve(c.courseGroupId);
            } else if (c.courseGroupId) {
                promise = hook.app.service('courseGroups').get(c.courseGroupId);
            } else {
                promise = Promise.resolve({ userIds: [] });
            }

            return promise.then(courseGroup => {
                return c.homeworkId.publicSubmissions // publicSubmissions allowes (everyone can see)
                    || c.homeworkId.teacherId.toString() == hook.params.account.userId.toString() // or user is teacher
                    || c.studentId.toString() == hook.params.account.userId.toString() // or is student (only needed for old tasks, in new tasks all users shoudl be in teamMembers)
                    || c.teamMembers.includes(hook.params.account.userId.toString()) // or is a teamMember
                    || courseGroup.userIds.includes(hook.params.account.userId.toString()); // or in the courseGroup
            });
        })).then(result => {
            (hook.result.data) ? (hook.result.data = data) : (hook.result = data);
        });
    }
    return Promise.resolve(hook);
};

const stringifyUserId = hook => {
    if ((hook.params.account || {}).userId) {
        hook.params.account.userId = hook.params.account.userId.toString();
    }
    return Promise.resolve(hook);
};

const insertSubmissionData = hook => {
    const submissionId = hook.id || hook.data.submissionId;
    if (submissionId) {
        const submissionService = hook.app.service('/submissions');
        return submissionService.get(submissionId, { account: { userId: hook.params.account.userId } })
            .then(submission => {
                hook.data.submission = submission;
                hook.data = JSON.parse(JSON.stringify(hook.data));
                hook.data.isTeamMember = false;
                hook.data.isOwner = false;
                if (hook.data.submission.studentId._id == hook.params.account.userId) {
                    hook.data.isOwner = true;
                    hook.data.isTeamMember = true;
                }
                if ((hook.data.submission.teamMembers || []).includes(hook.params.account.userId)) {
                    hook.data.isTeamMember = true;
                }
                return Promise.resolve(hook);
            })
            .catch(err => {
                return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach submission service" }));
            });
    }
    return Promise.resolve(hook);
};

const insertHomeworkData = hook => {
    const homeworkId = hook.data.homeworkId || (hook.data.submission || {}).homeworkId;
    if (homeworkId) {
        const homeworkService = hook.app.service('/homework');
        return homeworkService.get(homeworkId, { account: { userId: hook.params.account.userId } })
            .then(homework => {
                hook.data.homework = homework;
                // isTeacher?
                hook.data.isTeacher = false;
                if ((hook.data.homework.courseId.teacherIds || []).includes(hook.params.account.userId) ||
                    (hook.data.homework.teacherId == hook.params.account.userId)) {
                    hook.data.isTeacher = true;
                }
                return Promise.resolve(hook);
            })
            .catch(err => {
                return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach homework service" }));
            });
    }
    return Promise.reject(new errors.BadRequest());
};

const insertSubmissionsData = hook => {
    // get all the submissions for the homework
    const submissionService = hook.app.service('/submissions');
    return submissionService.find({
            query: {
                homeworkId: hook.data.homeworkId,
                $populate: ['studentId']
            }
        }).then((submissions) => {
            hook.data.submissions = submissions.data;
            return Promise.resolve(hook);
        })
        .catch(err => {
            return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach submission service" }));
        });
};

const preventNoTeamMember = hook => {
    if (!(hook.data.submission || {}).teamMembers) {
        hook.data.teamMembers = [hook.params.account.userId];
    }
    if (hook.method == "update" && (!hook.data.teamMembers || hook.data.teamMembers.length == 0)) {
        return Promise.reject(new errors.Conflict({
            "message": "Abgaben ohne TeamMember sind nicht erlaubt!"
        }));
    }
    return Promise.resolve(hook);
};

const setTeamMembers = hook => {
    if (!hook.data.teamMembers) { // if student (no grading) is going to submit without teamMembers set
        hook.data.teamMembers = [hook.params.account.userId];
    }
    if (!hook.data.teamMembers.includes(hook.params.account.userId)) {
        return Promise.reject(new errors.Conflict({
            "message": "Du kannst nicht ausschließlich für andere Abgeben. Füge dich selbst zur Abgabe hinzu!"
        }));
    }
};

const noSubmissionBefore = hook => {
    // check that no one has already submitted for the current User
    let submissionsForMe = hook.data.submissions.filter(submission => { // is there an submission for the current user?
        return (submission.teamMembers.includes(hook.params.account.userId)) ||
            ((submission.studentId || {})._id == hook.params.account.userId);
    });
    if (submissionsForMe.length > 0) {
        return Promise.reject(new errors.Conflict({
            "message": submissionsForMe[0].studentId.firstName + " " + submissionsForMe[0].studentId.lastName + " hat bereits für dich abgegeben!"
        }));
    }
    return Promise.resolve(hook);
};

const noDuplicateSubmissionForTeamMembers = hook => {
    if (!hook.data.isTeacher && hook.data.teamMembers) {
        // check if a teamMember submitted a solution on his own => display names
        let newTeamMembers = hook.data.teamMembers;
        if (hook.data.submission) {
            newTeamMembers = newTeamMembers.filter(teamMember => {
                return !hook.data.submission.teamMembers.includes(teamMember.toString());
            });
        }

        let toRemove = '';
        let submissionsForTeamMembers = hook.data.submissions.filter(submission => {
            for (var i = 0; i < newTeamMembers.length; i++) {
                const teamMember = newTeamMembers[i].toString();
                if (submission.teamMembers.includes(teamMember) ||
                    (((submission.studentId || {})._id || {}).toString() == teamMember)
                ) {
                    toRemove += (toRemove == '') ? '' : ', ';
                    toRemove += submission.studentId.firstName + ' ' + submission.studentId.lastName;
                    return true;
                }
            }
            return false;
        });
        if (submissionsForTeamMembers.length > 0) {
            return Promise.reject(new errors.Conflict({
                "message": toRemove + ((submissionsForTeamMembers.length == 1) ? ' hat' : ' haben') + ' bereits eine Lösung abgegeben! Entferne diese' + ((submissionsForTeamMembers.length == 1) ? 's Mitglied!' : ' Mitglieder!')
            }));
        } else {
            return Promise.resolve(hook);
        }
    }
};

const maxTeamMembers = hook => {
    if (!hook.data.isTeacher && hook.data.homework.teamSubmissions) {
        if ((hook.data.homework.maxTeamMembers || 0) >= 1 &&
            (hook.data.teamMembers || []).length > hook.data.homework.maxTeamMembers) {
            return Promise.reject(new errors.Conflict({
                "message": "Dein Team ist größer als erlaubt! ( maximal " + hook.data.homework.maxTeamMembers + " Teammitglieder erlaubt)"
            }));
        }
    } else {
        if ((hook.data.teamMembers || []).length > 1) {
            return Promise.reject(new errors.Conflict({
                "message": "Teamabgaben sind nicht erlaubt!"
            }));
        }
    }
    return Promise.resolve(hook);
};

const canRemoveOwner = hook => {
    if (hook.data.teamMembers &&
        !hook.data.teamMembers.includes(hook.data.submission.studentId)) {
        if (hook.data.isOwner) {
            return Promise.reject(new errors.Conflict({
                "message": "Du hast diese Abgabe erstellt. Du darfst dich nicht selbst von dieser löschen!"
            }));
        } else {
            return Promise.reject(new errors.Conflict({
                "message": "Du darfst den Ersteller nicht von der Abgabe löschen!"
            }));
        }
    }
    return Promise.resolve(hook);
};

const canGrade = hook => {
    if (!hook.data.isTeacher &&
        (Number.isInteger(hook.data.grade) || typeof hook.data.gradeComment == "string")) { // students try to grade? BLOCK!
        return Promise.reject(new errors.Forbidden());
    } else {
        return Promise.resolve(hook);
    }
};

const hasEditPermission = hook => {
    // may check that the teacher can't edit the submission itself (only grading allowed)
    if (hook.data.isTeamMember || hook.data.isTeacher) {
        return Promise.resolve(hook);
    } else {
        return Promise.reject(new errors.Forbidden());
    }
};

const hasDeletePermission = hook => {
    if (hook.data.isTeamMember) {
        return Promise.resolve(hook);
    } else {
        return Promise.reject(new errors.Forbidden());
    }
};

exports.before = {
    all: [auth.hooks.authenticate('jwt'), stringifyUserId],
    find: [globalHooks.hasPermission('SUBMISSIONS_VIEW'), globalHooks.mapPaginationQuery.bind(this)],
    get: [globalHooks.hasPermission('SUBMISSIONS_VIEW')],
    create: [globalHooks.hasPermission('SUBMISSIONS_CREATE'), insertHomeworkData, insertSubmissionsData, setTeamMembers, noSubmissionBefore, noDuplicateSubmissionForTeamMembers, maxTeamMembers, canGrade],
    update: [globalHooks.hasPermission('SUBMISSIONS_EDIT'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, hasEditPermission, preventNoTeamMember, canRemoveOwner, noDuplicateSubmissionForTeamMembers, maxTeamMembers, canGrade],
    patch: [globalHooks.hasPermission('SUBMISSIONS_EDIT'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, hasEditPermission, preventNoTeamMember, canRemoveOwner, noDuplicateSubmissionForTeamMembers, maxTeamMembers, globalHooks.permitGroupOperation, canGrade],
    remove: [globalHooks.hasPermission('SUBMISSIONS_CREATE'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, globalHooks.permitGroupOperation, hasDeletePermission]
};

exports.after = {
    all: [],
    find: [filterApplicableSubmissions],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
};<commit_msg>fix submission hook<commit_after>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication');
const errors = require('feathers-errors');

const filterApplicableSubmissions = hook => {
    let data = hook.result.data || hook.result;
    if (hook.params.account) {
        Promise.all(data.filter(function(e) {
            let c = JSON.parse(JSON.stringify(e));
            if (typeof c.teamMembers[0] === 'object') {
                c.teamMembers = c.teamMembers.map(e => { return e._id; }); // map teamMembers list to _id list (if $populate(d) is used)
            }

            let promise;
            if (typeof c.courseGroupId === 'object') {
                promise = Promise.resolve(c.courseGroupId);
            } else if (c.courseGroupId) {
                promise = hook.app.service('courseGroups').get(c.courseGroupId);
            } else {
                promise = Promise.resolve({ userIds: [] });
            }
            return promise.then(courseGroup => {
                return c.homeworkId.publicSubmissions // publicSubmissions allowes (everyone can see)
                    || (c.homeworkId.teacherId || {}).toString() == hook.params.account.userId.toString() // or user is teacher
                    || c.studentId.toString() == hook.params.account.userId.toString() // or is student (only needed for old tasks, in new tasks all users shoudl be in teamMembers)
                    || c.teamMembers.includes(hook.params.account.userId.toString()) // or is a teamMember
                    || courseGroup.userIds.includes(hook.params.account.userId.toString()); // or in the courseGroup
            });
        })).then(result => {
            (hook.result.data) ? (hook.result.data = data) : (hook.result = data);
        });
    }
    return Promise.resolve(hook);
};

const stringifyUserId = hook => {
    if ((hook.params.account || {}).userId) {
        hook.params.account.userId = hook.params.account.userId.toString();
    }
    return Promise.resolve(hook);
};

const insertSubmissionData = hook => {
    const submissionId = hook.id || hook.data.submissionId;
    if (submissionId) {
        const submissionService = hook.app.service('/submissions');
        return submissionService.get(submissionId, { account: { userId: hook.params.account.userId } })
            .then(submission => {
                hook.data.submission = submission;
                hook.data = JSON.parse(JSON.stringify(hook.data));
                hook.data.isTeamMember = false;
                hook.data.isOwner = false;
                if (hook.data.submission.studentId._id == hook.params.account.userId) {
                    hook.data.isOwner = true;
                    hook.data.isTeamMember = true;
                }
                if ((hook.data.submission.teamMembers || []).includes(hook.params.account.userId)) {
                    hook.data.isTeamMember = true;
                }
                return Promise.resolve(hook);
            })
            .catch(err => {
                return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach submission service" }));
            });
    }
    return Promise.resolve(hook);
};

const insertHomeworkData = hook => {
    const homeworkId = hook.data.homeworkId || (hook.data.submission || {}).homeworkId;
    if (homeworkId) {
        const homeworkService = hook.app.service('/homework');
        return homeworkService.get(homeworkId, { account: { userId: hook.params.account.userId } })
            .then(homework => {
                hook.data.homework = homework;
                // isTeacher?
                hook.data.isTeacher = false;
                if ((hook.data.homework.courseId.teacherIds || []).includes(hook.params.account.userId) ||
                    (hook.data.homework.teacherId == hook.params.account.userId)) {
                    hook.data.isTeacher = true;
                }
                return Promise.resolve(hook);
            })
            .catch(err => {
                return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach homework service" }));
            });
    }
    return Promise.reject(new errors.BadRequest());
};

const insertSubmissionsData = hook => {
    // get all the submissions for the homework
    const submissionService = hook.app.service('/submissions');
    return submissionService.find({
            query: {
                homeworkId: hook.data.homeworkId,
                $populate: ['studentId']
            }
        }).then((submissions) => {
            hook.data.submissions = submissions.data;
            return Promise.resolve(hook);
        })
        .catch(err => {
            return Promise.reject(new errors.GeneralError({ "message": "[500 INTERNAL ERROR] - can't reach submission service" }));
        });
};

const preventNoTeamMember = hook => {
    if (!(hook.data.submission || {}).teamMembers) {
        hook.data.teamMembers = [hook.params.account.userId];
    }
    if (hook.method == "update" && (!hook.data.teamMembers || hook.data.teamMembers.length == 0)) {
        return Promise.reject(new errors.Conflict({
            "message": "Abgaben ohne TeamMember sind nicht erlaubt!"
        }));
    }
    return Promise.resolve(hook);
};

const setTeamMembers = hook => {
    if (!hook.data.teamMembers) { // if student (no grading) is going to submit without teamMembers set
        hook.data.teamMembers = [hook.params.account.userId];
    }
    if (!hook.data.teamMembers.includes(hook.params.account.userId)) {
        return Promise.reject(new errors.Conflict({
            "message": "Du kannst nicht ausschließlich für andere Abgeben. Füge dich selbst zur Abgabe hinzu!"
        }));
    }
};

const noSubmissionBefore = hook => {
    // check that no one has already submitted for the current User
    let submissionsForMe = hook.data.submissions.filter(submission => { // is there an submission for the current user?
        return (submission.teamMembers.includes(hook.params.account.userId)) ||
            ((submission.studentId || {})._id == hook.params.account.userId);
    });
    if (submissionsForMe.length > 0) {
        return Promise.reject(new errors.Conflict({
            "message": submissionsForMe[0].studentId.firstName + " " + submissionsForMe[0].studentId.lastName + " hat bereits für dich abgegeben!"
        }));
    }
    return Promise.resolve(hook);
};

const noDuplicateSubmissionForTeamMembers = hook => {
    if (!hook.data.isTeacher && hook.data.teamMembers) {
        // check if a teamMember submitted a solution on his own => display names
        let newTeamMembers = hook.data.teamMembers;
        if (hook.data.submission) {
            newTeamMembers = newTeamMembers.filter(teamMember => {
                return !hook.data.submission.teamMembers.includes(teamMember.toString());
            });
        }

        let toRemove = '';
        let submissionsForTeamMembers = hook.data.submissions.filter(submission => {
            for (var i = 0; i < newTeamMembers.length; i++) {
                const teamMember = newTeamMembers[i].toString();
                if (submission.teamMembers.includes(teamMember) ||
                    (((submission.studentId || {})._id || {}).toString() == teamMember)
                ) {
                    toRemove += (toRemove == '') ? '' : ', ';
                    toRemove += submission.studentId.firstName + ' ' + submission.studentId.lastName;
                    return true;
                }
            }
            return false;
        });
        if (submissionsForTeamMembers.length > 0) {
            return Promise.reject(new errors.Conflict({
                "message": toRemove + ((submissionsForTeamMembers.length == 1) ? ' hat' : ' haben') + ' bereits eine Lösung abgegeben! Entferne diese' + ((submissionsForTeamMembers.length == 1) ? 's Mitglied!' : ' Mitglieder!')
            }));
        } else {
            return Promise.resolve(hook);
        }
    }
};

const maxTeamMembers = hook => {
    if (!hook.data.isTeacher && hook.data.homework.teamSubmissions) {
        if ((hook.data.homework.maxTeamMembers || 0) >= 1 &&
            (hook.data.teamMembers || []).length > hook.data.homework.maxTeamMembers) {
            return Promise.reject(new errors.Conflict({
                "message": "Dein Team ist größer als erlaubt! ( maximal " + hook.data.homework.maxTeamMembers + " Teammitglieder erlaubt)"
            }));
        }
    } else {
        if ((hook.data.teamMembers || []).length > 1) {
            return Promise.reject(new errors.Conflict({
                "message": "Teamabgaben sind nicht erlaubt!"
            }));
        }
    }
    return Promise.resolve(hook);
};

const canRemoveOwner = hook => {
    if (hook.data.teamMembers &&
        !hook.data.teamMembers.includes(hook.data.submission.studentId)) {
        if (hook.data.isOwner) {
            return Promise.reject(new errors.Conflict({
                "message": "Du hast diese Abgabe erstellt. Du darfst dich nicht selbst von dieser löschen!"
            }));
        } else {
            return Promise.reject(new errors.Conflict({
                "message": "Du darfst den Ersteller nicht von der Abgabe löschen!"
            }));
        }
    }
    return Promise.resolve(hook);
};

const canGrade = hook => {
    if (!hook.data.isTeacher &&
        (Number.isInteger(hook.data.grade) || typeof hook.data.gradeComment == "string")) { // students try to grade? BLOCK!
        return Promise.reject(new errors.Forbidden());
    } else {
        return Promise.resolve(hook);
    }
};

const hasEditPermission = hook => {
    // may check that the teacher can't edit the submission itself (only grading allowed)
    if (hook.data.isTeamMember || hook.data.isTeacher) {
        return Promise.resolve(hook);
    } else {
        return Promise.reject(new errors.Forbidden());
    }
};

const hasDeletePermission = hook => {
    if (hook.data.isTeamMember) {
        return Promise.resolve(hook);
    } else {
        return Promise.reject(new errors.Forbidden());
    }
};

exports.before = {
    all: [auth.hooks.authenticate('jwt'), stringifyUserId],
    find: [globalHooks.hasPermission('SUBMISSIONS_VIEW'), globalHooks.mapPaginationQuery.bind(this)],
    get: [globalHooks.hasPermission('SUBMISSIONS_VIEW')],
    create: [globalHooks.hasPermission('SUBMISSIONS_CREATE'), insertHomeworkData, insertSubmissionsData, setTeamMembers, noSubmissionBefore, noDuplicateSubmissionForTeamMembers, maxTeamMembers, canGrade],
    update: [globalHooks.hasPermission('SUBMISSIONS_EDIT'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, hasEditPermission, preventNoTeamMember, canRemoveOwner, noDuplicateSubmissionForTeamMembers, maxTeamMembers, canGrade],
    patch: [globalHooks.hasPermission('SUBMISSIONS_EDIT'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, hasEditPermission, preventNoTeamMember, canRemoveOwner, noDuplicateSubmissionForTeamMembers, maxTeamMembers, globalHooks.permitGroupOperation, canGrade],
    remove: [globalHooks.hasPermission('SUBMISSIONS_CREATE'), insertSubmissionData, insertHomeworkData, insertSubmissionsData, globalHooks.permitGroupOperation, hasDeletePermission]
};

exports.after = {
    all: [],
    find: [filterApplicableSubmissions],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
};<|endoftext|>


<commit_before>(function(){
    'use strict';

angular.module('chirp', ['ui.router','ngSanitize','ngCookies'])
    .constant("config",
    {
        "api": "http://localhost:3000/api/v1",
        //"api": "http://chirp.dimotta.net/api/v1",
        "elapsedtime": 5000
    })
    .config(['$logProvider','$stateProvider','$urlRouterProvider', function($logProvider,$stateProvider,$urlRouterProvider)
    {
        $logProvider.debugEnabled(true);

        $urlRouterProvider.otherwise("/public");

        $stateProvider
            .state('public', {
                url: "/public",
                templateUrl: 'partials/public-view.html',
                controller: 'PublicCtrl'
            })
            .state('home', {
                url: "/home",
                templateUrl: 'partials/home-view.html',
                controller: 'HomeCtrl'
            })
            .state('login', {
                url: "/login",
                templateUrl: 'partials/login-form-view.html',
                controller: 'LoginCtrl'
            })
            .state('following', {
                url: "/following",
                templateUrl: 'partials/following-list-view.html',
                controller: 'FollowingCtrl'
            })
            .state('followers', {
                url: "/followers",
                templateUrl: 'partials/followers-list-view.html',
                controller: 'FollowersCtrl'
            })
            .state('signup', {
                url: "/signup",
                templateUrl: 'partials/register-form-view.html',
                controller: 'RegisterCtrl'
            })
    }
]);

})();
<commit_msg>update app.js<commit_after>(function(){
    'use strict';

angular.module('chirp', ['ui.router','ngSanitize','ngCookies'])
    .constant("config",
    {
        //"api": "http://localhost:3000/api/v1",
        "api": "http://chirp.dimotta.net/api/v1",
        "elapsedtime": 5000
    })
    .config(['$logProvider','$stateProvider','$urlRouterProvider', function($logProvider,$stateProvider,$urlRouterProvider)
    {
        $logProvider.debugEnabled(true);

        $urlRouterProvider.otherwise("/public");

        $stateProvider
            .state('public', {
                url: "/public",
                templateUrl: 'partials/public-view.html',
                controller: 'PublicCtrl'
            })
            .state('home', {
                url: "/home",
                templateUrl: 'partials/home-view.html',
                controller: 'HomeCtrl'
            })
            .state('login', {
                url: "/login",
                templateUrl: 'partials/login-form-view.html',
                controller: 'LoginCtrl'
            })
            .state('following', {
                url: "/following",
                templateUrl: 'partials/following-list-view.html',
                controller: 'FollowingCtrl'
            })
            .state('followers', {
                url: "/followers",
                templateUrl: 'partials/followers-list-view.html',
                controller: 'FollowersCtrl'
            })
            .state('signup', {
                url: "/signup",
                templateUrl: 'partials/register-form-view.html',
                controller: 'RegisterCtrl'
            })
    }
]);

})();
<|endoftext|>