<commit_before>import Registry from './registry';
import { exists } from './utils/file'
import * as Task from './task';
import Host from './host.js';
import exec from './exec';
import Whois from './helper/whois';

class Ssl {
    constructor(host) {
        this.host = host;
        this.db = Registry.get('Database');
    }

    async enable (method) {
        let hostInfo = await this.host.info();
        if (hostInfo.ssl === 0) {
            let allowedMethods = ['dns', 'apache', 'manual']
            await this.checkSslModEnabled()
            if (allowedMethods.includes(method)) {
                if (method === 'manual') {
                    let checkCerts = await this.checkCertsExist(hostInfo.path)
                    if (checkCerts.includes(false)) {
                        throw new Error('SSL Certs missing')
                    } else {
                        let certsEqual = await this.checkCertsEqual(hostInfo.path)
                        if (certsEqual) {
                            await this.db
                            .table('host')
                            .where({
                                client: this.host.client.name,
                                host: this.host.name
                            })
                            .update({
                                ssl: 1
                            });
                            await this.host.refresh(this);
                        } else {
                            throw new Error('SSL Certs not Equal')
                        }

                    }
                } else if (method === 'dns') {
                    // await this.checkDomainDNSRecords(hostInfo)
                    await Task.run('ssl.create', {
                        ...hostInfo,
                        method
                    });
                    let certsEqual = await this.checkCertsEqual(hostInfo.path)
                    if (certsEqual) {
                        await this.db
                        .table('host')
                        .where({
                            client: this.host.client.name,
                            host: this.host.name
                        })
                        .update({
                            ssl: 1
                        });
                        await this.host.refresh(this);
                    } else {
                        throw new Error('SSL Certs not Equal')
                    }
                } else if (method === 'apache') {
                    await this.checkDomainDNSRecords(hostInfo)
                    await this.checkApacheCertBotPluginInstalled()
                    await Task.run('ssl.create', {
                        ...hostInfo,
                        method
                    });
                    let certsEqual = await this.checkCertsEqual(hostInfo.path)
                    if (certsEqual) {
                        await this.db
                        .table('host')
                        .where({
                            client: this.host.client.name,
                            host: this.host.name
                        })
                        .update({
                            ssl: 1
                        });
                        await this.host.refresh(this);
                    } else {
                        throw new Error('SSL Certs not Equal')
                    }
                }
            } else {
                throw new Error('Unknown Method, read the manuals')
            }
        } else {
            throw new Error('SSL already enabled for ' + hostInfo.host)
        }
    }

    host(hostname) {
        return (new Host(this, hostname));
    }

    async disable () {
        await this.checkSslModEnabled()
        await this.db
            .table('host')
            .where({
                client: this.host.client.name,
                host: this.host.name
            })
            .update({
                ssl: 0
            });
            await this.host.refresh(this);
    }

    async checkCertsExist (path) {
        return Promise.all([exists(path + '/certs/fullchain.pem'), exists(path + '/certs/privkey.pem')])
    }

    async checkCertsEqual (path) {
        try {
            let privateKeyFile = path + '/certs/privkey.pem'
            let publicKeyFile = path + '/certs/fullchain.pem'
            let privateKeyCheckSum = await exec(`openssl rsa --modulus --noout --in ${privateKeyFile} | openssl sha256`);
            let publicKeyCheckSum = await exec('openssl x509 -noout -modulus -in {{publicKeyFile}} | openssl sha256', { publicKeyFile });
            privateKeyCheckSum = privateKeyCheckSum.replace(/(\r\n|\n|\r)/gm, "").replace('(stdin)= ', '');
            publicKeyCheckSum = publicKeyCheckSum.replace(/(\r\n|\n|\r)/gm, "").replace('(stdin)= ', '');
            if (privateKeyCheckSum === publicKeyCheckSum) {
                return true
            } else {
                return false
            }
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning(err.message);
            }
            throw err;
        }
    }

    async checkSslModEnabled () {
        try {
            await exec("apachectl -t -D DUMP_MODULES | grep ssl_module | awk '{print $1}'");
            return true
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('SSL Module disabled in Apache2');
            }
            throw err;
        }
    }

    async checkDomainDNSRecords (host) {
        let domains = [
            host.host,
            ...host.alias
        ]
        let whois = await this.getWhoisForDomain(host.host)
        let serverIp = await this.getAvantiServerIP()
        let promises = []
        domains.forEach((domain) => {
            promises.push(this.getCurrentIPForDomain(domain, whois.nserver.split(' ')[0]))
        })
        return await Promise.all(promises).then((element) => {
            element.forEach((ip, index) => {
                if (ip !== serverIp) {
                    throw new Task.Warning('DNS Check Error: IP Pointing to Domain Record not same as Server (check ' + domains[index] + ')');
                }
            })
        })
    }

    async getWhoisForDomain (domain) {
        try {
            return await Whois(domain)
        } catch (err) {
            throw new Task.Warning(err.message);
        }
    }

    async getCurrentIPForDomain (domain, nameserver) {
        try {
            return exec('dig {{domain}} @{{nameserver}} +short', {
                domain,
                nameserver
            }).then((element) => {
                 return element.replace(/(\r\n|\n|\r)/gm, "");
            })
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('SSL Module disabled in Apache2');
            }
            throw err;
        }
    }

    async getAvantiServerIP () {
        return await exec("ip route get 1 | awk '{print $NF;exit}'")
    }

    async checkApacheCertBotPluginInstalled () {
        try {
            return await exec("dpkg -l | grep -E '^ii' | grep python3-certbot-apache")
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('Apache2 Module not installed  (phyton3-certbot-apache)');
            }
            throw err;
        }
    }
}

export default Ssl;
<commit_msg>trim spaces<commit_after>import Registry from './registry';
import { exists } from './utils/file'
import * as Task from './task';
import Host from './host.js';
import exec from './exec';
import Whois from './helper/whois';

class Ssl {
    constructor(host) {
        this.host = host;
        this.db = Registry.get('Database');
    }

    async enable (method) {
        let hostInfo = await this.host.info();
        if (hostInfo.ssl === 0) {
            let allowedMethods = ['dns', 'apache', 'manual']
            await this.checkSslModEnabled()
            if (allowedMethods.includes(method)) {
                if (method === 'manual') {
                    let checkCerts = await this.checkCertsExist(hostInfo.path)
                    if (checkCerts.includes(false)) {
                        throw new Error('SSL Certs missing')
                    } else {
                        let certsEqual = await this.checkCertsEqual(hostInfo.path)
                        if (certsEqual) {
                            await this.db
                            .table('host')
                            .where({
                                client: this.host.client.name,
                                host: this.host.name
                            })
                            .update({
                                ssl: 1
                            });
                            await this.host.refresh(this);
                        } else {
                            throw new Error('SSL Certs not Equal')
                        }

                    }
                } else if (method === 'dns') {
                    // await this.checkDomainDNSRecords(hostInfo)
                    await Task.run('ssl.create', {
                        ...hostInfo,
                        method
                    });
                    let certsEqual = await this.checkCertsEqual(hostInfo.path)
                    if (certsEqual) {
                        await this.db
                        .table('host')
                        .where({
                            client: this.host.client.name,
                            host: this.host.name
                        })
                        .update({
                            ssl: 1
                        });
                        await this.host.refresh(this);
                    } else {
                        throw new Error('SSL Certs not Equal')
                    }
                } else if (method === 'apache') {
                    await this.checkDomainDNSRecords(hostInfo)
                    await this.checkApacheCertBotPluginInstalled()
                    await Task.run('ssl.create', {
                        ...hostInfo,
                        method
                    });
                    let certsEqual = await this.checkCertsEqual(hostInfo.path)
                    if (certsEqual) {
                        await this.db
                        .table('host')
                        .where({
                            client: this.host.client.name,
                            host: this.host.name
                        })
                        .update({
                            ssl: 1
                        });
                        await this.host.refresh(this);
                    } else {
                        throw new Error('SSL Certs not Equal')
                    }
                }
            } else {
                throw new Error('Unknown Method, read the manuals')
            }
        } else {
            throw new Error('SSL already enabled for ' + hostInfo.host)
        }
    }

    host(hostname) {
        return (new Host(this, hostname));
    }

    async disable () {
        await this.checkSslModEnabled()
        await this.db
            .table('host')
            .where({
                client: this.host.client.name,
                host: this.host.name
            })
            .update({
                ssl: 0
            });
            await this.host.refresh(this);
    }

    async checkCertsExist (path) {
        return Promise.all([exists(path + '/certs/fullchain.pem'), exists(path + '/certs/privkey.pem')])
    }

    async checkCertsEqual (path) {
        try {
            let privateKeyFile = path + '/certs/privkey.pem'
            let publicKeyFile = path + '/certs/fullchain.pem'
            let privateKeyCheckSum = await exec(`openssl rsa --modulus --noout --in ${privateKeyFile} | openssl sha256`);
            let publicKeyCheckSum = await exec('openssl x509 -noout -modulus -in {{publicKeyFile}} | openssl sha256', { publicKeyFile });
            privateKeyCheckSum = privateKeyCheckSum.replace(/(\r\n|\n|\r)/gm, "").replace('(stdin)= ', '');
            publicKeyCheckSum = publicKeyCheckSum.replace(/(\r\n|\n|\r)/gm, "").replace('(stdin)= ', '');
            if (privateKeyCheckSum === publicKeyCheckSum) {
                return true
            } else {
                return false
            }
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning(err.message);
            }
            throw err;
        }
    }

    async checkSslModEnabled () {
        try {
            await exec("apachectl -t -D DUMP_MODULES | grep ssl_module | awk '{print $1}'");
            return true
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('SSL Module disabled in Apache2');
            }
            throw err;
        }
    }

    async checkDomainDNSRecords (host) {
        let domains = [
            host.host,
            ...host.alias
        ]
        let whois = await this.getWhoisForDomain(host.host)
        let serverIp = await this.getAvantiServerIP()
        let promises = []
        domains.forEach((domain) => {
            promises.push(this.getCurrentIPForDomain(domain, whois.nserver.split(' ')[0]))
        })
        return await Promise.all(promises).then((element) => {
            element.forEach((ip, index) => {
                if (ip !== serverIp) {
                    throw new Task.Warning('DNS Check Error: IP Pointing to Domain Record not same as Server (check ' + domains[index] + ')');
                }
            })
        })
    }

    async getWhoisForDomain (domain) {
        try {
            return await Whois(domain)
        } catch (err) {
            throw new Task.Warning(err.message);
        }
    }

    async getCurrentIPForDomain (domain, nameserver) {
        try {
            return exec('dig {{domain}} @{{nameserver}} +short', {
                domain,
                nameserver
            }).then((element) => {
                 return element.replace(/(\r\n|\n|\r)/gm, "");
            })
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('SSL Module disabled in Apache2');
            }
            throw err;
        }
    }

    async getAvantiServerIP () {
        return await exec("ip route get 1 | awk '{print $NF;exit}'").then((element) => {
             return element.replace(/(\r\n|\n|\r)/gm, "");
        })
    }

    async checkApacheCertBotPluginInstalled () {
        try {
            return await exec("dpkg -l | grep -E '^ii' | grep python3-certbot-apache")
        } catch (err) {
            if (err.code === 1) {
                throw new Task.Warning('Apache2 Module not installed  (phyton3-certbot-apache)');
            }
            throw err;
        }
    }
}

export default Ssl;
<|endoftext|>


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

  MC.Views.Home = Backbone.View.extend({
    el: "#content",

    template: Handlebars.compile($("#home").html()),

    events: {
      'click #submit': 'submitForm',
      "keydown textarea[name='intro']": 'updateCharLimit',
    },

    updateCharLimit: function() {
      var length = this.$("textarea[name='intro']")
        .val()
        .length;
      var remaining = 256 - length;
      var $countdownEl = this.$('.countdown');

      if (remaining < 128 && remaining >= 64) {
        $countdownEl
          .removeClass('label-info label-danger')
          .addClass('label-warning');
      } else if (remaining < 64) {
        $countdownEl
          .removeClass('label-info label-warning')
          .addClass('label-danger');
      } else {
        $countdownEl
          .removeClass('label-warning label-danger')
          .addClass('label-info');
      }

      $countdownEl.html(remaining + ' characters remaining');
    },

    submitForm: function() {
      var fields = {};

      fields.email = this.$("input[name='email']");
      fields.course = this.$("input[name='course']");
      fields.display_name = this.$("input[name='displayname']");
      fields.intro = this.$("textarea[name='intro']");

      var data = {
        course: fields.course.val().trim(),
        email: fields.email.val().trim(),
        display_name: fields.display_name.val().trim(),
        intro: fields.intro.val().trim()
      };

      var newForm = new MC.Models.Form(data);
      var errors = newForm.validate(data);
      var containsErrors = false;

      for (var k in fields) {
        var formField = fields[k].parent();
        if (errors[k]) {
          containsErrors = true;
          formField.addClass('has-error');
        } else {
          formField.removeClass('has-error');
          formField.addClass('has-success');
        }
      }

      if (!containsErrors) {
        var $formLoaderEl = this.$('.processing-loader').show();
        var minDelay = 1000; // ms
        $formLoaderEl.addClass('form-processing');
        var options = {
          success: function(model, res, options) {
            var currTime = (new Date()).getTime();
            var diff = currTime - options.timeSent;
            // Play delay animation :)
            setTimeout(function() {
              $formLoaderEl.removeClass('form-processing');
              $formLoaderEl.hide();
              $('#myModal').modal('hide');
              (new MC.Views.Alert()).render();
            }, (diff < minDelay) ? minDelay - diff : 0);
          },
          error: function(model, res, options) {
            $formLoaderEl.removeClass('form-processing');
            $formLoaderEl.hide();
            alert("Something went wrong");
          },
          validate: false,
          timeSent: (new Date()).getTime()
        }
        newForm.save(data, options);
      }

    },

    render: function() {
      this.$el.html(this.template());
      var $courseTypeaheadEl = this.$("input[name='course'].twitter-typeahead");

      // https://github.com/twitter/typeahead.js/issues/492
      $courseTypeaheadEl.typeahead({
        name: 'courses',
        valueKey: 'name',
        template: Handlebars.compile("
{{name}} {{provider.name}}
"),
        remote: {
          url: 'course/%QUERY',
          beforeSend: function(e) {
            $courseTypeaheadEl
            .addClass('autocomplete-loading');},
          complete: function(e) {
            $courseTypeaheadEl
            .removeClass('autocomplete-loading');}
        },
        limit: 5,
      });

      return this;
    }

  });

})();
<commit_msg>fixed tense issue and handles negatives<commit_after>(function () {
  "use strict";

  MC.Views.Home = Backbone.View.extend({
    el: "#content",

    template: Handlebars.compile($("#home").html()),

    events: {
      'click #submit': 'submitForm',
      "keydown textarea[name='intro']": 'updateCharLimit',
    },

    updateCharLimit: function() {
      var length = this.$("textarea[name='intro']")
        .val()
        .length;
      var remaining = 256 - length;
      var $countdownEl = this.$('.countdown');
      var getWarningMessage = function(remaining) {
        var num = Math.abs(remaining);
        var msg = (new String(num));
        msg += (num === 1) ? " character" : " characters";
        msg += (remaining >= 0) ? " remaining" : " overlimit";
        return msg;
      };

      if (remaining < 128 && remaining >= 64) {
        $countdownEl
          .removeClass('label-info label-danger')
          .addClass('label-warning');
      } else if (remaining < 64) {
        $countdownEl
          .removeClass('label-info label-warning')
          .addClass('label-danger');
      } else {
        $countdownEl
          .removeClass('label-warning label-danger')
          .addClass('label-info');
      }

      $countdownEl.html(getWarningMessage(remaining));

    },

    submitForm: function() {
      var fields = {};

      fields.email = this.$("input[name='email']");
      fields.course = this.$("input[name='course']");
      fields.display_name = this.$("input[name='displayname']");
      fields.intro = this.$("textarea[name='intro']");

      var data = {
        course: fields.course.val().trim(),
        email: fields.email.val().trim(),
        display_name: fields.display_name.val().trim(),
        intro: fields.intro.val().trim()
      };

      var newForm = new MC.Models.Form(data);
      var errors = newForm.validate(data);
      var containsErrors = false;

      for (var k in fields) {
        var formField = fields[k].parent();
        if (errors[k]) {
          containsErrors = true;
          formField.addClass('has-error');
        } else {
          formField.removeClass('has-error');
          formField.addClass('has-success');
        }
      }

      if (!containsErrors) {
        var $formLoaderEl = this.$('.processing-loader').show();
        var minDelay = 1000; // ms
        $formLoaderEl.addClass('form-processing');
        var options = {
          success: function(model, res, options) {
            var currTime = (new Date()).getTime();
            var diff = currTime - options.timeSent;
            // Play delay animation :)
            setTimeout(function() {
              $formLoaderEl.removeClass('form-processing');
              $formLoaderEl.hide();
              $('#myModal').modal('hide');
              (new MC.Views.Alert()).render();
            }, (diff < minDelay) ? minDelay - diff : 0);
          },
          error: function(model, res, options) {
            $formLoaderEl.removeClass('form-processing');
            $formLoaderEl.hide();
            alert("Something went wrong");
          },
          validate: false,
          timeSent: (new Date()).getTime()
        }
        newForm.save(data, options);
      }

    },

    render: function() {
      this.$el.html(this.template());
      var $courseTypeaheadEl = this.$("input[name='course'].twitter-typeahead");

      // https://github.com/twitter/typeahead.js/issues/492
      $courseTypeaheadEl.typeahead({
        name: 'courses',
        valueKey: 'name',
        template: Handlebars.compile("
{{name}} {{provider.name}}
"),
        remote: {
          url: 'course/%QUERY',
          beforeSend: function(e) {
            $courseTypeaheadEl
            .addClass('autocomplete-loading');},
          complete: function(e) {
            $courseTypeaheadEl
            .removeClass('autocomplete-loading');}
        },
        limit: 5,
      });

      return this;
    }

  });

})();
<|endoftext|>


<commit_before>/* global Travis */
import { observer } from '@ember/object';

import { isEmpty } from '@ember/utils';
import { Promise as EmberPromise } from 'rsvp';
import Service from '@ember/service';
import config from 'travis/config/environment';
import { computed } from 'ember-decorators/object';
import { alias } from 'ember-decorators/object/computed';
import { service } from 'ember-decorators/service';

export default Service.extend({
  @service router: null,
  @service flashes: null,
  @service store: null,
  @service storage: null,
  @service sessionStorage: null,
  @service ajax: null,

  state: 'signed-out',
  receivingEnd: `${location.protocol}//${location.host}`,
  tokenExpiredMsg: 'You\'ve been signed out, because your access token has expired.',

  token() {
    return this.get('sessionStorage').getItem('travis.token');
  },

  assetToken() {
    return JSON.parse(this.get('sessionStorage').getItem('travis.user'))['token'];
  },

  endpoint: config.authEndpoint || config.apiEndpoint,

  signOut() {
    this.get('sessionStorage').clear();
    this.get('storage').clear();
    this.set('state', 'signed-out');
    this.set('user', null);
    this.get('store').unloadAll();
    this.set('currentUser', null);
    this.clearNonAuthFlashes();
  },

  signIn(data) {
    if (data) {
      this.autoSignIn(data);
    } else {
      this.set('state', 'signing-in');
      window.location = `${this.get('endpoint')}/auth/handshake?redirect_uri=${location}`;
    }
  },

  autoSignIn(data) {
    if (!data) {
      data = this.userDataFrom(this.get('sessionStorage')) ||
             this.userDataFrom(this.get('storage'));
    }

    if (data) {
      this.setData(data);
      this.refreshUserData().then(() => {
      }, (xhr) => {
        // if xhr is not defined it means that scopes are not correct,
        // so log the user out. Also log the user out if the response is 401
        // or 403
        if (!xhr || (xhr.status === 401 || xhr.status === 403)) {
          this.get('flashes').error(this.get('tokenExpiredMsg'));
          this.signOut();
        }
      });
    }
  },

  userDataFrom(storage) {
    let token, user, userJSON;
    userJSON = storage.getItem('travis.user');
    if (userJSON != null) {
      user = JSON.parse(userJSON);
    }
    if (user != null ? user.user : void 0) {
      user = user.user;
    }
    token = storage.getItem('travis.token');
    if (user && token && this.validateUser(user)) {
      return {
        user,
        token
      };
    } else {
      storage.removeItem('travis.user');
      storage.removeItem('travis.token');
      return null;
    }
  },

  validateUser(user) {
    let fieldsToValidate, isTravisBecome;
    fieldsToValidate = ['id', 'login', 'token'];
    isTravisBecome = this.get('sessionStorage').getItem('travis.become');
    if (!isTravisBecome) {
      fieldsToValidate.push('correct_scopes');
    }
    if (this.get('features.proVersion')) {
      fieldsToValidate.push('channels');
    }
    return fieldsToValidate.every(field => this.validateHas(field, user)) &&
      (isTravisBecome || user.correct_scopes);
  },

  validateHas(field, user) {
    if (user[field]) {
      return true;
    } else {
      return false;
    }
  },

  setData(data) {
    let user;
    this.storeData(data, this.get('sessionStorage'));
    if (!this.userDataFrom(this.get('storage'))) {
      this.storeData(data, this.get('storage'));
    }
    user = this.loadUser(data.user);
    this.set('currentUser', user);
    this.set('state', 'signed-in');
    Travis.trigger('user:signed_in', data.user);
  },

  refreshUserData(user) {
    if (!user) {
      let data = this.userDataFrom(this.get('sessionStorage')) ||
                 this.userDataFrom(this.get('storage'));
      if (data) {
        user = data.user;
      }
    }
    if (user) {
      return this.get('ajax').get(`/users/${user.id}`).then((data) => {
        let userRecord;
        if (data.user.correct_scopes) {
          userRecord = this.loadUser(data.user);
          userRecord.get('permissions');
          if (this.get('signedIn')) {
            data.user.token = user.token;
            this.storeData(data, this.get('sessionStorage'));
            this.storeData(data, this.get('storage'));
            Travis.trigger('user:refreshed', data.user);
          }
        } else {
          return EmberPromise.reject();
        }
      });
    } else {
      return EmberPromise.resolve();
    }
  },

  @computed('state')
  signedIn(state) {
    return state === 'signed-in';
  },

  @computed('state')
  signedOut(state) {
    return state === 'signed-out';
  },

  @computed('state')
  signingIn(state) {
    return state === 'signing-in';
  },

  storeData(data, storage) {
    if (data.token) {
      storage.setItem('travis.token', data.token);
    }
    return storage.setItem('travis.user', JSON.stringify(data.user));
  },

  loadUser(user) {
    let store = this.get('store'),
      userClass = store.modelFor('user'),
      serializer = store.serializerFor('user'),
      normalized = serializer.normalizeResponse(store, userClass, user, null, 'findRecord');

    store.push(normalized);
    return store.recordForId('user', user.id);
  },

  expectedOrigin() {
    let endpoint = this.get('endpoint');
    if (endpoint && endpoint[0] === '/') {
      return this.receivingEnd;
    } else {
      let matches = endpoint.match(/^https?:\/\/[^\/]*/);
      if (matches && matches.length) {
        return matches[0];
      }
    }
  },

  clearNonAuthFlashes() {
    const flashMessages = this.get('flashes.flashes.content') || [];
    const errorMessages = flashMessages.filterBy('type', 'error');
    if (!isEmpty(errorMessages)) {
      const errMsg = errorMessages.get('firstObject.message');
      if (errMsg !== this.get('tokenExpiredMsg')) {
        return this.get('flashes').clear();
      }
    } else {
      return this.get('flashes').clear();
    }
  },

  sync() {
    return this.get('currentUser').sync();
  },

  syncingDidChange: observer('isSyncing', 'currentUser', function () {
    const user = this.get('currentUser');
    if (user && user.get('isSyncing') && !user.get('syncedAt')) {
      return this.get('router').transitionTo('first_sync');
    }
  }),

  @computed('currentUser.{login,name}')
  userName(login, name) {
    return name || login;
  },

  @computed('currentUser.gravatarId')
  gravatarUrl(gravatarId) {
    return `${location.protocol}//www.gravatar.com/avatar/${gravatarId}?s=48&d=mm`;
  },

  // eslint-ignore-next-line
  @alias('currentUser.permissions') permissions: null,
});
<commit_msg>Add custom post-auth redirect from plans page (#1386)<commit_after>/* global Travis */
import { observer } from '@ember/object';

import { isEmpty } from '@ember/utils';
import { Promise as EmberPromise } from 'rsvp';
import Service from '@ember/service';
import config from 'travis/config/environment';
import { computed } from 'ember-decorators/object';
import { alias } from 'ember-decorators/object/computed';
import { service } from 'ember-decorators/service';

export default Service.extend({
  @service router: null,
  @service flashes: null,
  @service store: null,
  @service storage: null,
  @service sessionStorage: null,
  @service ajax: null,

  state: 'signed-out',
  receivingEnd: `${location.protocol}//${location.host}`,
  tokenExpiredMsg: 'You\'ve been signed out, because your access token has expired.',

  token() {
    return this.get('sessionStorage').getItem('travis.token');
  },

  assetToken() {
    return JSON.parse(this.get('sessionStorage').getItem('travis.user'))['token'];
  },

  endpoint: config.authEndpoint || config.apiEndpoint,

  signOut() {
    this.get('sessionStorage').clear();
    this.get('storage').clear();
    this.set('state', 'signed-out');
    this.set('user', null);
    this.get('store').unloadAll();
    this.set('currentUser', null);
    this.clearNonAuthFlashes();
  },

  signIn(data) {
    if (data) {
      this.autoSignIn(data);
    } else {
      this.set('state', 'signing-in');

      let url = new URL(window.location.href);

      if (url.pathname === '/plans') {
        url.pathname = '/';
      }

      window.location = `${this.get('endpoint')}/auth/handshake?redirect_uri=${url}`;
    }
  },

  autoSignIn(data) {
    if (!data) {
      data = this.userDataFrom(this.get('sessionStorage')) ||
             this.userDataFrom(this.get('storage'));
    }

    if (data) {
      this.setData(data);
      this.refreshUserData().then(() => {
      }, (xhr) => {
        // if xhr is not defined it means that scopes are not correct,
        // so log the user out. Also log the user out if the response is 401
        // or 403
        if (!xhr || (xhr.status === 401 || xhr.status === 403)) {
          this.get('flashes').error(this.get('tokenExpiredMsg'));
          this.signOut();
        }
      });
    }
  },

  userDataFrom(storage) {
    let token, user, userJSON;
    userJSON = storage.getItem('travis.user');
    if (userJSON != null) {
      user = JSON.parse(userJSON);
    }
    if (user != null ? user.user : void 0) {
      user = user.user;
    }
    token = storage.getItem('travis.token');
    if (user && token && this.validateUser(user)) {
      return {
        user,
        token
      };
    } else {
      storage.removeItem('travis.user');
      storage.removeItem('travis.token');
      return null;
    }
  },

  validateUser(user) {
    let fieldsToValidate, isTravisBecome;
    fieldsToValidate = ['id', 'login', 'token'];
    isTravisBecome = this.get('sessionStorage').getItem('travis.become');
    if (!isTravisBecome) {
      fieldsToValidate.push('correct_scopes');
    }
    if (this.get('features.proVersion')) {
      fieldsToValidate.push('channels');
    }
    return fieldsToValidate.every(field => this.validateHas(field, user)) &&
      (isTravisBecome || user.correct_scopes);
  },

  validateHas(field, user) {
    if (user[field]) {
      return true;
    } else {
      return false;
    }
  },

  setData(data) {
    let user;
    this.storeData(data, this.get('sessionStorage'));
    if (!this.userDataFrom(this.get('storage'))) {
      this.storeData(data, this.get('storage'));
    }
    user = this.loadUser(data.user);
    this.set('currentUser', user);
    this.set('state', 'signed-in');
    Travis.trigger('user:signed_in', data.user);
  },

  refreshUserData(user) {
    if (!user) {
      let data = this.userDataFrom(this.get('sessionStorage')) ||
                 this.userDataFrom(this.get('storage'));
      if (data) {
        user = data.user;
      }
    }
    if (user) {
      return this.get('ajax').get(`/users/${user.id}`).then((data) => {
        let userRecord;
        if (data.user.correct_scopes) {
          userRecord = this.loadUser(data.user);
          userRecord.get('permissions');
          if (this.get('signedIn')) {
            data.user.token = user.token;
            this.storeData(data, this.get('sessionStorage'));
            this.storeData(data, this.get('storage'));
            Travis.trigger('user:refreshed', data.user);
          }
        } else {
          return EmberPromise.reject();
        }
      });
    } else {
      return EmberPromise.resolve();
    }
  },

  @computed('state')
  signedIn(state) {
    return state === 'signed-in';
  },

  @computed('state')
  signedOut(state) {
    return state === 'signed-out';
  },

  @computed('state')
  signingIn(state) {
    return state === 'signing-in';
  },

  storeData(data, storage) {
    if (data.token) {
      storage.setItem('travis.token', data.token);
    }
    return storage.setItem('travis.user', JSON.stringify(data.user));
  },

  loadUser(user) {
    let store = this.get('store'),
      userClass = store.modelFor('user'),
      serializer = store.serializerFor('user'),
      normalized = serializer.normalizeResponse(store, userClass, user, null, 'findRecord');

    store.push(normalized);
    return store.recordForId('user', user.id);
  },

  expectedOrigin() {
    let endpoint = this.get('endpoint');
    if (endpoint && endpoint[0] === '/') {
      return this.receivingEnd;
    } else {
      let matches = endpoint.match(/^https?:\/\/[^\/]*/);
      if (matches && matches.length) {
        return matches[0];
      }
    }
  },

  clearNonAuthFlashes() {
    const flashMessages = this.get('flashes.flashes.content') || [];
    const errorMessages = flashMessages.filterBy('type', 'error');
    if (!isEmpty(errorMessages)) {
      const errMsg = errorMessages.get('firstObject.message');
      if (errMsg !== this.get('tokenExpiredMsg')) {
        return this.get('flashes').clear();
      }
    } else {
      return this.get('flashes').clear();
    }
  },

  sync() {
    return this.get('currentUser').sync();
  },

  syncingDidChange: observer('isSyncing', 'currentUser', function () {
    const user = this.get('currentUser');
    if (user && user.get('isSyncing') && !user.get('syncedAt')) {
      return this.get('router').transitionTo('first_sync');
    }
  }),

  @computed('currentUser.{login,name}')
  userName(login, name) {
    return name || login;
  },

  @computed('currentUser.gravatarId')
  gravatarUrl(gravatarId) {
    return `${location.protocol}//www.gravatar.com/avatar/${gravatarId}?s=48&d=mm`;
  },

  // eslint-ignore-next-line
  @alias('currentUser.permissions') permissions: null,
});
<|endoftext|>


<commit_before>//= require ./lib/noConflict
//= require ./vendor/modern-stack
//= require ./lib
//= require ./extension
//= require ./models
//= require ./plugins
//= require ./views
//= require ./screens
//= require ./components/Base
//= require ./components/enabled
//= require ./extension/LateLoaded
<commit_msg>Load screens after components<commit_after>//= require ./lib/noConflict
//= require ./vendor/modern-stack
//= require ./lib
//= require ./extension
//= require ./models
//= require ./plugins
//= require ./views
//= require ./components/Base
//= require ./components/enabled
//= require ./extension/LateLoaded
//= require ./screens
<|endoftext|>


<commit_before>// Add editor instance to 'N' & emit event for plugins
//

/*global ace*/

'use strict';

var _ = require('lodash');

var TEXT_MARGIN = 5;
var TOOLBAR = '$$ JSON.stringify(N.config.mdedit) $$';

// Compile toolbar config
//
var compileToolbarConfig = _.memoize(function (name) {
  var buttonName;

  return _.reduce(TOOLBAR[name], function (result, buttonParams, key) {
    if (!buttonParams) {
      return result;
    }

    buttonName = key.indexOf('separator') === 0 ? 'separator' : key;

    if (buttonParams === true) {
      result.push(TOOLBAR.buttons[buttonName]);
    } else {
      result.push(_.defaults({}, buttonParams, TOOLBAR.buttons[buttonName]));
    }

    return result;
  }, []).sort(function (a, b) {
    return a.priority - b.priority;
  });
});

// Editor init
//
function MDEdit() {
  this.commands = {};
  this.__attachments__ = [];
  this.__options__ = null;
  this.__layout__ = null;
  this.__minHeight__ = 0;
}

// Create new layout and show
//
// Options:
//
// - parseOptions (Object) - optional, object with plugins config like
//   `{ images: true, links: true, attachments: false }`, default `{}`
// - text (String) - optional, text, default empty string
// - attachments (Array) - optional, attachments, default empty array
// - toolbar (String) - optional, name of toolbar config, default `default`
//
// returns jQuery object
//
// Events:
//
// - `show.nd.mdedit` - before editor shown (when animation start)
// - `shown.nd.mdedit` - on editor shown
// - `hide.nd.mdedit` - before editor hide (when animation start)
// - `hidden.nd.mdedit` - on editor hide
// - `submit.nd.mdedit` - on done button press (if you want to prevent editor closing - call `event.preventDefault()`)
// - `change.nd.mdedit` - on update preview, you can save drafts on this event
//
MDEdit.prototype.show = function (options) {
  var self = this;
  var $oldLayout = this.__layout__;

  this.__layout__ = $(N.runtime.render('mdedit'));
  this.__options__ = _.clone(options);
  this.__options__.toolbar = compileToolbarConfig(this.__options__.toolbar || 'default');
  this.__options__.parseOptions = this.__options__.parseOptions || {};

  $('body').append(this.__layout__);

  this.__initAce__();
  this.__initResize__();
  this.__initToolbar__();

  this.text(options.text || '');
  this.attachments(options.attachments || []);

  setTimeout(function () {
    self.__layout__.trigger('show');
    self.__layout__.animate({ bottom: 0 }, $oldLayout ? 0 : 'fast', function () {
      self.__layout__.trigger('shown');

      // Hide previous editor
      if ($oldLayout) {
        $oldLayout.trigger('hide');
        $oldLayout.trigger('hidden');
        $oldLayout.remove();
      }

      self.__ace__.resize();
    });
  }, 0);

  return this.__layout__;
};

// Hide editor
//
MDEdit.prototype.hide = function () {
  var self = this;
  var $layout = this.__layout__;

  if (!$layout) {
    return;
  }

  setTimeout(function () {
    $layout.trigger('hide');
    $layout.animate({ bottom: -$layout.height() }, 'fast', function () {
      self.__layout__ = null;
      $layout.trigger('hidden');
      $layout.remove();
    });
  }, 0);
};

// Get/set text
//
MDEdit.prototype.text = function (text) {
  if (!text) {
    return this.__ace__.getValue();
  }

  this.__ace__.setValue(text, -1);

  this.__updatePreview__();
};

// Get/set attachments
//
MDEdit.prototype.attachments = function (attachments) {
  if (!attachments) {
    return this.__attachments__;
  }

  this.__attachments__ = attachments;

  if (this.__attachments__.length === 0) {
    this.__layout__.addClass('mdedit__m-no-attachments');
  } else {
    this.__layout__.removeClass('mdedit__m-no-attachments');
  }

  this.__updatePreview__();
};

// Get/set parse options
//
MDEdit.prototype.parseOptions = function (parseOptions) {
  if (!parseOptions) {
    return this.__options__.parseOptions;
  }

  this.__options__.parseOptions = parseOptions;

  this.__initToolbar__();
  this.__updatePreview__();
};

// Set initial Ace options
//
MDEdit.prototype.__initAce__ = function () {
  this.__ace__ = ace.edit(this.__layout__.find('.mdedit__edit-area').get(0));

  this.__ace__.renderer.scrollMargin.top = TEXT_MARGIN;
  this.__ace__.renderer.scrollMargin.bottom = TEXT_MARGIN;

  var aceSession = this.__ace__.getSession();

  aceSession.setMode('ace/mode/markdown');

  this.__ace__.setOptions({
    showLineNumbers: false,
    showGutter: false,
    highlightActiveLine: false
  });

  aceSession.setUseWrapMode(true);

  aceSession.on('change', this.__updatePreview__.bind(this));

  this.__ace__.focus();
};

// Add editor resize handler
//
MDEdit.prototype.__initResize__ = function () {
  var self = this;
  var $body = $('body');

  self.__minHeight__ = parseInt(this.__layout__.css('minHeight'), 10);
  self.__layout__.height(self.__minHeight__);

  this.__layout__.find('.mdedit__resizer').on('mousedown touchstart', function (event) {
    var clickStart = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
    var currentHeight = parseInt(self.__layout__.height(), 10);

    self.__layout__.addClass('mdedit__m-resizing');

    $body
      .on('mouseup.nd.mdedit touchend.nd.mdedit', function () {
        $body.off('.nd.mdedit');
        self.__layout__.removeClass('mdedit__m-resizing');
      })
      .on('mousemove.nd.mdedit touchmove.nd.mdedit', _.debounce(function (event) {
        var point = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
        var newHeight = currentHeight - (point.pageY - clickStart.pageY);

        self.__layout__.height(newHeight > self.__minHeight__ ? newHeight : self.__minHeight__);
        self.__ace__.resize();
      }, 20, { maxWait: 20 }));

    return false;
  });
};

// Update attachments, preview and save draft
//
MDEdit.prototype.__updatePreview__ = _.debounce(function () {
  var self = this;

  self.__layout__.trigger('change');

  N.parse(
    {
      text: this.text(),
      attachments: this.attachments(),
      options: this.__options__.parseOptions
    },
    function (err, result) {
      if (err) {
        // TODO: notify about err
        throw err;
      }

      self.__layout__.find('.mdedit__preview').html(N.runtime.render('mdedit.preview', {
        user_hid: N.runtime.user_hid,
        html: result.html,
        attachments: result.tail
      }));

      self.__layout__.find('.mdedit-attachments').html(N.runtime.render('mdedit.attachments', {
        attachments: self.attachments()
      }));
    }
  );
}, 500, { maxWait: 500, leading: true });

// Update toolbar button list
//
MDEdit.prototype.__initToolbar__ = function () {
  var self = this;
  var $toolbar = this.__layout__.find('.mdedit__toolbar');

  // Get actual buttons
  var buttons = _.reduce(this.__options__.toolbar, function (result, btn) {

    // If parser plugin inactive - remove button
    if (self.__options__.parseOptions[btn.depend] === false) {
      return result;
    }

    // If duplicate separator - remove it
    if (btn.separator && result.length > 0 && result[result.length - 1].separator) {
      return result;
    }

    result.push(btn);

    return result;
  }, []);

  // If first item is separator - remove
  if (buttons.length > 0 && buttons[0].separator) {
    buttons.shift();
  }

  // If last item is separator - remove
  if (buttons.length > 0 && buttons[buttons.length - 1].separator) {
    buttons.pop();
  }

  // Render toolbar
  $toolbar.html(N.runtime.render('mdedit.toolbar', {
    buttons: buttons
  }));

  // Disable all hotkeys
  this.__ace__.commands.removeCommands(Object.keys(this.commands));

  // Enable active button's hotkeys
  buttons.forEach(function (button) {
    if (!button.command || !button.bind_key || !self.commands[button.command]) {
      return;
    }

    self.__ace__.commands.addCommand({
      name: button.command,
      bindKey: button.bind_key,
      exec: self.commands[button.command].bind(self)
    });
  });
};

// Toolbar button click
//
N.wire.on('mdedit.toolbar:click', function toolbar_click(data) {
  var command = N.MDEdit.commands[data.$this.data('command')].bind(N.MDEdit);

  if (command) {
    command(N.MDEdit.__ace__);

    // Restore focus on editor after command execution
    N.MDEdit.__ace__.focus();
  }
});

// Attachment click
//
N.wire.on('mdedit.attachments:insert', function attachments_insert(data) {
  var url = N.router.linkTo('users.media', { user_hid: N.runtime.user_hid, media_id: data.$this.data('media-id') });

  N.MDEdit.__ace__.insert('![](' + url + ')');
  N.MDEdit.__ace__.focus();

  data.event.stopPropagation();
});

// Remove attachment
//
N.wire.on('mdedit.attachments:remove', function attachments_insert(data) {
  var id = data.$this.data('media-id');
  var attachments = N.MDEdit.attachments();

  attachments = _.remove(attachments, function (val) { return val.media_id !== id; });
  N.MDEdit.attachments(attachments);
  data.event.stopPropagation();
});

// Done handler
//
N.wire.on('mdedit.submit', function done_click() {
  var event = new $.Event('submit');

  N.MDEdit.__layout__.trigger(event);

  if (!event.isDefaultPrevented()) {
    N.MDEdit.hide();
  }
});

// Hide on cancel
//
N.wire.on('mdedit.cancel', function close() {
  N.MDEdit.hide();
});

// Collapse/expand editor
//
N.wire.on('mdedit.collapse', function collapse() {
  var $layout = N.MDEdit.__layout__;

  // Expand
  if ($layout.hasClass('mdedit__m-collapsed')) {
    $layout.removeClass('mdedit__m-collapsed');
    $layout.height(N.MDEdit.__minHeight__);

  // Collapse
  } else {
    $layout.css('minHeight', 0);
    $layout.addClass('mdedit__m-collapsed');
  }
});

// Dragdrop file to editor
//
N.wire.on('mdedit:dd', function mdedit_dd(data) {
  var $layout = N.MDEdit.__layout__;
  var x0, y0, x1, y1, ex, ey, uploaderData;

  switch (data.event.type) {
    case 'dragenter':
      $layout.addClass('mdedit__m-active');
      break;
    case 'dragleave':
      // 'dragleave' occurs when user move cursor over child HTML element
      // track this situation and don't remove 'active' class
      // http://stackoverflow.com/questions/10867506/
      x0 = $layout.offset().left;
      y0 = $layout.offset().top;
      x1 = x0 + $layout.outerWidth();
      y1 = y0 + $layout.outerHeight();
      ex = data.event.originalEvent.pageX;
      ey = data.event.originalEvent.pageY;

      if (ex > x1 || ex < x0 || ey > y1 || ey < y0) {
        $layout.removeClass('mdedit__m-active');
      }
      break;
    case 'drop':
      $layout.removeClass('mdedit__m-active');

      if (data.event.dataTransfer && data.event.dataTransfer.files && data.event.dataTransfer.files.length) {

        uploaderData = {
          files: data.event.dataTransfer.files,
          url: N.router.linkTo('users.media.upload'),
          config: 'users.uploader_config',
          uploaded: null
        };

        N.wire.emit('users.uploader:add', uploaderData, function () {
          var attachments = N.MDEdit.attachments();

          uploaderData.uploaded.forEach(function (media) {
            attachments.unshift(_.pick(media, [ 'media_id', 'file_name', 'type' ]));
          });

          N.MDEdit.attachments(attachments);
        });
      }
      break;
    default:
  }
});

// Add editor instance to 'N' & emit event for plugins
//
N.wire.once('init:assets', function (__, callback) {
  N.MDEdit = new MDEdit();

  N.wire.emit('init:mdedit', {}, callback);
});
<commit_msg>mdedit - restore proper height on expand<commit_after>// Add editor instance to 'N' & emit event for plugins
//

/*global ace*/

'use strict';

var _ = require('lodash');

var TEXT_MARGIN = 5;
var TOOLBAR = '$$ JSON.stringify(N.config.mdedit) $$';

// Compile toolbar config
//
var compileToolbarConfig = _.memoize(function (name) {
  var buttonName;

  return _.reduce(TOOLBAR[name], function (result, buttonParams, key) {
    if (!buttonParams) {
      return result;
    }

    buttonName = key.indexOf('separator') === 0 ? 'separator' : key;

    if (buttonParams === true) {
      result.push(TOOLBAR.buttons[buttonName]);
    } else {
      result.push(_.defaults({}, buttonParams, TOOLBAR.buttons[buttonName]));
    }

    return result;
  }, []).sort(function (a, b) {
    return a.priority - b.priority;
  });
});

// Editor init
//
function MDEdit() {
  this.commands = {};
  this.__attachments__ = [];
  this.__options__ = null;
  this.__layout__ = null;
  this.__minHeight__ = 0;
}

// Create new layout and show
//
// Options:
//
// - parseOptions (Object) - optional, object with plugins config like
//   `{ images: true, links: true, attachments: false }`, default `{}`
// - text (String) - optional, text, default empty string
// - attachments (Array) - optional, attachments, default empty array
// - toolbar (String) - optional, name of toolbar config, default `default`
//
// returns jQuery object
//
// Events:
//
// - `show.nd.mdedit` - before editor shown (when animation start)
// - `shown.nd.mdedit` - on editor shown
// - `hide.nd.mdedit` - before editor hide (when animation start)
// - `hidden.nd.mdedit` - on editor hide
// - `submit.nd.mdedit` - on done button press (if you want to prevent editor closing - call `event.preventDefault()`)
// - `change.nd.mdedit` - on update preview, you can save drafts on this event
//
MDEdit.prototype.show = function (options) {
  var self = this;
  var $oldLayout = this.__layout__;

  this.__layout__ = $(N.runtime.render('mdedit'));
  this.__options__ = _.clone(options);
  this.__options__.toolbar = compileToolbarConfig(this.__options__.toolbar || 'default');
  this.__options__.parseOptions = this.__options__.parseOptions || {};

  $('body').append(this.__layout__);

  this.__initAce__();
  this.__initResize__();
  this.__initToolbar__();

  this.text(options.text || '');
  this.attachments(options.attachments || []);

  setTimeout(function () {
    self.__layout__.trigger('show');
    self.__layout__.animate({ bottom: 0 }, $oldLayout ? 0 : 'fast', function () {
      self.__layout__.trigger('shown');

      // Hide previous editor
      if ($oldLayout) {
        $oldLayout.trigger('hide');
        $oldLayout.trigger('hidden');
        $oldLayout.remove();
      }

      self.__ace__.resize();
    });
  }, 0);

  return this.__layout__;
};

// Hide editor
//
MDEdit.prototype.hide = function () {
  var self = this;
  var $layout = this.__layout__;

  if (!$layout) {
    return;
  }

  setTimeout(function () {
    $layout.trigger('hide');
    $layout.animate({ bottom: -$layout.height() }, 'fast', function () {
      self.__layout__ = null;
      $layout.trigger('hidden');
      $layout.remove();
    });
  }, 0);
};

// Get/set text
//
MDEdit.prototype.text = function (text) {
  if (!text) {
    return this.__ace__.getValue();
  }

  this.__ace__.setValue(text, -1);

  this.__updatePreview__();
};

// Get/set attachments
//
MDEdit.prototype.attachments = function (attachments) {
  if (!attachments) {
    return this.__attachments__;
  }

  this.__attachments__ = attachments;

  if (this.__attachments__.length === 0) {
    this.__layout__.addClass('mdedit__m-no-attachments');
  } else {
    this.__layout__.removeClass('mdedit__m-no-attachments');
  }

  this.__updatePreview__();
};

// Get/set parse options
//
MDEdit.prototype.parseOptions = function (parseOptions) {
  if (!parseOptions) {
    return this.__options__.parseOptions;
  }

  this.__options__.parseOptions = parseOptions;

  this.__initToolbar__();
  this.__updatePreview__();
};

// Set initial Ace options
//
MDEdit.prototype.__initAce__ = function () {
  this.__ace__ = ace.edit(this.__layout__.find('.mdedit__edit-area').get(0));

  this.__ace__.renderer.scrollMargin.top = TEXT_MARGIN;
  this.__ace__.renderer.scrollMargin.bottom = TEXT_MARGIN;

  var aceSession = this.__ace__.getSession();

  aceSession.setMode('ace/mode/markdown');

  this.__ace__.setOptions({
    showLineNumbers: false,
    showGutter: false,
    highlightActiveLine: false
  });

  aceSession.setUseWrapMode(true);

  aceSession.on('change', this.__updatePreview__.bind(this));

  this.__ace__.focus();
};

// Add editor resize handler
//
MDEdit.prototype.__initResize__ = function () {
  var self = this;
  var $body = $('body');

  self.__minHeight__ = parseInt(this.__layout__.css('minHeight'), 10);
  self.__layout__.height(self.__minHeight__);

  this.__layout__.find('.mdedit__resizer').on('mousedown touchstart', function (event) {
    var clickStart = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
    var currentHeight = parseInt(self.__layout__.height(), 10);

    self.__layout__.addClass('mdedit__m-resizing');

    $body
      .on('mouseup.nd.mdedit touchend.nd.mdedit', function () {
        $body.off('.nd.mdedit');
        self.__layout__.removeClass('mdedit__m-resizing');
      })
      .on('mousemove.nd.mdedit touchmove.nd.mdedit', _.debounce(function (event) {
        var point = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
        var newHeight = currentHeight - (point.pageY - clickStart.pageY);

        self.__layout__.height(newHeight > self.__minHeight__ ? newHeight : self.__minHeight__);
        self.__ace__.resize();
      }, 20, { maxWait: 20 }));

    return false;
  });
};

// Update attachments, preview and save draft
//
MDEdit.prototype.__updatePreview__ = _.debounce(function () {
  var self = this;

  self.__layout__.trigger('change');

  N.parse(
    {
      text: this.text(),
      attachments: this.attachments(),
      options: this.__options__.parseOptions
    },
    function (err, result) {
      if (err) {
        // TODO: notify about err
        throw err;
      }

      self.__layout__.find('.mdedit__preview').html(N.runtime.render('mdedit.preview', {
        user_hid: N.runtime.user_hid,
        html: result.html,
        attachments: result.tail
      }));

      self.__layout__.find('.mdedit-attachments').html(N.runtime.render('mdedit.attachments', {
        attachments: self.attachments()
      }));
    }
  );
}, 500, { maxWait: 500, leading: true });

// Update toolbar button list
//
MDEdit.prototype.__initToolbar__ = function () {
  var self = this;
  var $toolbar = this.__layout__.find('.mdedit__toolbar');

  // Get actual buttons
  var buttons = _.reduce(this.__options__.toolbar, function (result, btn) {

    // If parser plugin inactive - remove button
    if (self.__options__.parseOptions[btn.depend] === false) {
      return result;
    }

    // If duplicate separator - remove it
    if (btn.separator && result.length > 0 && result[result.length - 1].separator) {
      return result;
    }

    result.push(btn);

    return result;
  }, []);

  // If first item is separator - remove
  if (buttons.length > 0 && buttons[0].separator) {
    buttons.shift();
  }

  // If last item is separator - remove
  if (buttons.length > 0 && buttons[buttons.length - 1].separator) {
    buttons.pop();
  }

  // Render toolbar
  $toolbar.html(N.runtime.render('mdedit.toolbar', {
    buttons: buttons
  }));

  // Disable all hotkeys
  this.__ace__.commands.removeCommands(Object.keys(this.commands));

  // Enable active button's hotkeys
  buttons.forEach(function (button) {
    if (!button.command || !button.bind_key || !self.commands[button.command]) {
      return;
    }

    self.__ace__.commands.addCommand({
      name: button.command,
      bindKey: button.bind_key,
      exec: self.commands[button.command].bind(self)
    });
  });
};

// Toolbar button click
//
N.wire.on('mdedit.toolbar:click', function toolbar_click(data) {
  var command = N.MDEdit.commands[data.$this.data('command')].bind(N.MDEdit);

  if (command) {
    command(N.MDEdit.__ace__);

    // Restore focus on editor after command execution
    N.MDEdit.__ace__.focus();
  }
});

// Attachment click
//
N.wire.on('mdedit.attachments:insert', function attachments_insert(data) {
  var url = N.router.linkTo('users.media', { user_hid: N.runtime.user_hid, media_id: data.$this.data('media-id') });

  N.MDEdit.__ace__.insert('![](' + url + ')');
  N.MDEdit.__ace__.focus();

  data.event.stopPropagation();
});

// Remove attachment
//
N.wire.on('mdedit.attachments:remove', function attachments_insert(data) {
  var id = data.$this.data('media-id');
  var attachments = N.MDEdit.attachments();

  attachments = _.remove(attachments, function (val) { return val.media_id !== id; });
  N.MDEdit.attachments(attachments);
  data.event.stopPropagation();
});

// Done handler
//
N.wire.on('mdedit.submit', function done_click() {
  var event = new $.Event('submit');

  N.MDEdit.__layout__.trigger(event);

  if (!event.isDefaultPrevented()) {
    N.MDEdit.hide();
  }
});

// Hide on cancel
//
N.wire.on('mdedit.cancel', function close() {
  N.MDEdit.hide();
});

// Collapse/expand editor
//
N.wire.on('mdedit.collapse', function collapse() {
  var $layout = N.MDEdit.__layout__;

  // Expand
  if ($layout.hasClass('mdedit__m-collapsed')) {
    $layout.removeClass('mdedit__m-collapsed');

  // Collapse
  } else {
    $layout.css('minHeight', 0);
    $layout.addClass('mdedit__m-collapsed');
  }
});

// Dragdrop file to editor
//
N.wire.on('mdedit:dd', function mdedit_dd(data) {
  var $layout = N.MDEdit.__layout__;
  var x0, y0, x1, y1, ex, ey, uploaderData;

  switch (data.event.type) {
    case 'dragenter':
      $layout.addClass('mdedit__m-active');
      break;
    case 'dragleave':
      // 'dragleave' occurs when user move cursor over child HTML element
      // track this situation and don't remove 'active' class
      // http://stackoverflow.com/questions/10867506/
      x0 = $layout.offset().left;
      y0 = $layout.offset().top;
      x1 = x0 + $layout.outerWidth();
      y1 = y0 + $layout.outerHeight();
      ex = data.event.originalEvent.pageX;
      ey = data.event.originalEvent.pageY;

      if (ex > x1 || ex < x0 || ey > y1 || ey < y0) {
        $layout.removeClass('mdedit__m-active');
      }
      break;
    case 'drop':
      $layout.removeClass('mdedit__m-active');

      if (data.event.dataTransfer && data.event.dataTransfer.files && data.event.dataTransfer.files.length) {

        uploaderData = {
          files: data.event.dataTransfer.files,
          url: N.router.linkTo('users.media.upload'),
          config: 'users.uploader_config',
          uploaded: null
        };

        N.wire.emit('users.uploader:add', uploaderData, function () {
          var attachments = N.MDEdit.attachments();

          uploaderData.uploaded.forEach(function (media) {
            attachments.unshift(_.pick(media, [ 'media_id', 'file_name', 'type' ]));
          });

          N.MDEdit.attachments(attachments);
        });
      }
      break;
    default:
  }
});

// Add editor instance to 'N' & emit event for plugins
//
N.wire.once('init:assets', function (__, callback) {
  N.MDEdit = new MDEdit();

  N.wire.emit('init:mdedit', {}, callback);
});
<|endoftext|>


<commit_before>function GameState() { }

var types = {
  PLAYER: 1,
  BULLET: 2
}

GameState.prototype.connectWebsocket = function() {
  var ws = new WebSocket('ws://localhost:1337', 'echo-protocol');
  //var ws = new WebSocket('ws://192.168.177.22:1337', 'echo-protocol');
  var that = this;
  this.ws = ws;
  this.wsReady = false;
  var that = this;
  this.players = {};
  console.log("connecting to websocket");
  ws.addEventListener('open', function(e) {
    that.wsReady = true;
    console.log("Connected");
    ws.send(JSON.stringify({
      type: 'join',
      name: new Player().name
    }));
  });
  ws.addEventListener('message', function(e) {
    message = JSON.parse(e.data);
    if(message.type == 'state') {
      oldstates = that.states;
      that.states = [that.states[1]
                    ,that.states[2]
                    ,message.state];
    } else if(message.type == 'join') {
      that.players[message.id] = new Player(message.name);
      if(message.you) {
        that.youId = message.id;
        var team = message.team == 0 ? 'light' : 'dark';
        console.log('el teamo', team);
        document.querySelector('body').classList.remove('dark');
        document.querySelector('body').classList.add('light');
        document.querySelector('body').classList.add(team);
      }
    }
  });
};

GameState.prototype.init = function() {
  this.bg = loadImage('res/ggj-bg.jpg');
  this.bgDark = loadImage('res/ggj-bg-dark.jpg');
  this.bgLight = loadImage('res/ggj-bg-light.jpg');
  this.playerImgLight = loadImage('res/player-light.png');
  this.playerImgDark = loadImage('res/player.png');
  this.cpNeutralImg = loadImage('res/marker.png');
  this.connectWebsocket();
  this.scoreL = 8;
  this.scoreD = 0;
  this.cameraZoom = 0.5;
  this.cameraX = 0;
  this.cameraY = 0;
  this.states = [];
};

GameState.prototype.pause = function() {
};

GameState.prototype.resume = function() {
  var that = this;
  this.elements = [
    [function() {
    }, {x: 7.5, y: 4, w: 1, h: 1}],
    [function() {
      that.audioButton.toggleActivated();
    }, {x: 15, y: 0, w: 1, h: 1}]
  ];
  this.audioButton = new AudioButton();
  var playerName = document.getElementById('player-name-input').value;
  this.player = new Player(playerName);
  localStorage.playerName = playerName;
};

GameState.prototype.render = function(ctx) {
  this.scoreL = 10 + 10 * Math.sin(+new Date() / 10000);
  this.scoreD = 10;

  var states = this.states;
  if(states[0]) {
    if(tick < states[0].tick){
      tick = states[0].tick; //global variables <3  ...
      console.log("Local tick too long behind");
    }
    if(tick >= states[2].tick){
      tick = states[2].tick - 1; //Don't go past last tick, remember we are adding subticks too
      console.log("Local tick too far ahead");
    }

    var state = tick >= states[1].tick ? states[1] : states[0];
    var state_next = tick >= states[1].tick ? states[2] : states[1];

    var coeff = (tick + dt/15 - state.tick) / (state_next.tick - state.tick);

    var players      = state.players;
    var players_next = state_next.players;

    var you = players[this.youId];
    var you_next = players_next[this.youId];
    var you_x = you.x * (1 - coeff) + you_next.x * coeff;
    var you_y = you.y * (1 - coeff) + you_next.y * coeff;
    this.cameraX = you_x;
    this.cameraY = you_y;

    ctx.save();
    ctx.translate(8 * GU - this.cameraX * GU * this.cameraZoom,
        4.5 * GU - this.cameraY * GU * this.cameraZoom);
    ctx.scale(this.cameraZoom, this.cameraZoom);
    ctx.save();
    ctx.scale(16 * GU / 1920 * 4, 16 * GU / 1920 * 4);
    ctx.drawImage(this.bg, 0, 0);
    ctx.globalAlpha = clamp(0, this.scoreL - this.scoreD - 10, 20) / 40;
    ctx.drawImage(this.bgDark, 0, 0);
    ctx.globalAlpha = clamp(0, this.scoreD - this.scoreL - 10, 20) / 40;
    ctx.drawImage(this.bgLight, 0, 0);
    ctx.restore();

    var capture_points      = state.capture_points;
    var capture_points_next = state_next.capture_points;
    for(var i in capture_points) {
      CapturePoint.prototype.render.call(
          capture_points[i],
          ctx,
          capture_points_next[i],
          this.cpNeutralImg);
    }

    for(var i in players) {
      var player = players[i];
      var player_next = players_next[i];
      var name = this.players[i].name;
      Character.prototype.render.call(
          player,
          ctx,
          player_next,
          coeff,
          this.playerImgLight,
          this.playerImgDark,
          name);
    }

    var bullets      = state.bullets;
    var bullets_next = state_next.bullets;
    for(var i in bullets) {
      var bullet = bullets[i];
      var bullet_next = bullets_next[i];
      Bullet.prototype.render.call(bullet, ctx, bullet_next, coeff);
    }

    ctx.restore();
  }

  this.audioButton.render();
};

GameState.prototype.update = function() {
  var that = this;

  if(MOUSE.scrollY) {
    this.cameraZoom *= 1 / ((MOUSE.scrollY + 1000) / 1000);
    this.cameraZoom = clamp(0.1, this.cameraZoom, 3);
  }

  if(this.wsReady) {
    var inputs = [];
    this.ws.send(JSON.stringify({
      type: 'inputs',
      inputs: [
      KEYS[87] || KEYS[38], // W, up arrow
      KEYS[83] || KEYS[40], // S, down arrow
      KEYS[65] || KEYS[37], // A, left arrow
      KEYS[68] || KEYS[39],  // D, right arrow
      MOUSE.left || KEYS[13], // enter
      MOUSE.right,
      MOUSE.x - 8 + this.cameraX,
      MOUSE.y - 4.5 + this.cameraY
      ]
    }));
  }
};
<commit_msg>Try to fix server crash<commit_after>function GameState() { }

var types = {
  PLAYER: 1,
  BULLET: 2
}

GameState.prototype.connectWebsocket = function() {
  var ws = new WebSocket('ws://localhost:1337', 'echo-protocol');
  //var ws = new WebSocket('ws://192.168.177.22:1337', 'echo-protocol');
  var that = this;
  this.ws = ws;
  this.wsReady = false;
  var that = this;
  this.players = {};
  console.log("connecting to websocket");
  ws.addEventListener('open', function(e) {
    that.wsReady = true;
    console.log("Connected");
    ws.send(JSON.stringify({
      type: 'join',
      name: new Player().name
    }));
  });
  ws.addEventListener('message', function(e) {
    message = JSON.parse(e.data);
    if(message.type == 'state') {
      oldstates = that.states;
      that.states = [that.states[1]
                    ,that.states[2]
                    ,message.state];
    } else if(message.type == 'join') {
      that.players[message.id] = new Player(message.name);
      if(message.you) {
        that.youId = message.id;
        var team = message.team == 0 ? 'light' : 'dark';
        console.log('el teamo', team);
        document.querySelector('body').classList.remove('dark');
        document.querySelector('body').classList.add('light');
        document.querySelector('body').classList.add(team);
      }
    }
  });
};

GameState.prototype.init = function() {
  this.bg = loadImage('res/ggj-bg.jpg');
  this.bgDark = loadImage('res/ggj-bg-dark.jpg');
  this.bgLight = loadImage('res/ggj-bg-light.jpg');
  this.playerImgLight = loadImage('res/player-light.png');
  this.playerImgDark = loadImage('res/player.png');
  this.cpNeutralImg = loadImage('res/marker.png');
  this.connectWebsocket();
  this.scoreL = 8;
  this.scoreD = 0;
  this.cameraZoom = 0.5;
  this.cameraX = 0;
  this.cameraY = 0;
  this.states = [];
};

GameState.prototype.pause = function() {
};

GameState.prototype.resume = function() {
  var that = this;
  this.elements = [
    [function() {
    }, {x: 7.5, y: 4, w: 1, h: 1}],
    [function() {
      that.audioButton.toggleActivated();
    }, {x: 15, y: 0, w: 1, h: 1}]
  ];
  this.audioButton = new AudioButton();
  var playerName = document.getElementById('player-name-input').value;
  this.player = new Player(playerName);
  localStorage.playerName = playerName;
};

GameState.prototype.render = function(ctx) {
  this.scoreL = 10 + 10 * Math.sin(+new Date() / 10000);
  this.scoreD = 10;

  var states = this.states;
  if(states[0]) {
    if(tick < states[0].tick){
      tick = states[0].tick; //global variables <3  ...
      console.log("Local tick too long behind");
    }
    if(tick >= states[2].tick){
      tick = states[2].tick - 1; //Don't go past last tick, remember we are adding subticks too
      console.log("Local tick too far ahead");
    }

    var state = tick >= states[1].tick ? states[1] : states[0];
    var state_next = tick >= states[1].tick ? states[2] : states[1];

    var coeff = (tick + dt/15 - state.tick) / (state_next.tick - state.tick);

    var players      = state.players;
    var players_next = state_next.players;

    var you = players[this.youId];
    var you_next = players_next[this.youId];
    if(you_next){
      var you_x = you.x * (1 - coeff) + you_next.x * coeff;
      var you_y = you.y * (1 - coeff) + you_next.y * coeff;
      this.cameraX = you_x;
      this.cameraY = you_y;
    }else{
      this.cameraX = you.x;
      this.cameraY = you.y;
    }

    ctx.save();
    ctx.translate(8 * GU - this.cameraX * GU * this.cameraZoom,
        4.5 * GU - this.cameraY * GU * this.cameraZoom);
    ctx.scale(this.cameraZoom, this.cameraZoom);
    ctx.save();
    ctx.scale(16 * GU / 1920 * 4, 16 * GU / 1920 * 4);
    ctx.drawImage(this.bg, 0, 0);
    ctx.globalAlpha = clamp(0, this.scoreL - this.scoreD - 10, 20) / 40;
    ctx.drawImage(this.bgDark, 0, 0);
    ctx.globalAlpha = clamp(0, this.scoreD - this.scoreL - 10, 20) / 40;
    ctx.drawImage(this.bgLight, 0, 0);
    ctx.restore();

    var capture_points      = state.capture_points;
    var capture_points_next = state_next.capture_points;
    for(var i in capture_points) {
      CapturePoint.prototype.render.call(
          capture_points[i],
          ctx,
          capture_points_next[i],
          this.cpNeutralImg);
    }

    for(var i in players) {
      var player = players[i];
      var player_next = players_next[i];
      var name = this.players[i].name;
      Character.prototype.render.call(
          player,
          ctx,
          player_next,
          coeff,
          this.playerImgLight,
          this.playerImgDark,
          name);
    }

    var bullets      = state.bullets;
    var bullets_next = state_next.bullets;
    for(var i in bullets) {
      var bullet = bullets[i];
      var bullet_next = bullets_next[i];
      Bullet.prototype.render.call(bullet, ctx, bullet_next, coeff);
    }

    ctx.restore();
  }

  this.audioButton.render();
};

GameState.prototype.update = function() {
  var that = this;

  if(MOUSE.scrollY) {
    this.cameraZoom *= 1 / ((MOUSE.scrollY + 1000) / 1000);
    this.cameraZoom = clamp(0.1, this.cameraZoom, 3);
  }

  if(this.wsReady) {
    var inputs = [];
    this.ws.send(JSON.stringify({
      type: 'inputs',
      inputs: [
      KEYS[87] || KEYS[38], // W, up arrow
      KEYS[83] || KEYS[40], // S, down arrow
      KEYS[65] || KEYS[37], // A, left arrow
      KEYS[68] || KEYS[39],  // D, right arrow
      MOUSE.left || KEYS[13], // enter
      MOUSE.right,
      MOUSE.x - 8 + this.cameraX,
      MOUSE.y - 4.5 + this.cameraY
      ]
    }));
  }
};
<|endoftext|>


<commit_before>$(document).ready(function() {
    $('#clothing_type').select2({
	placeholder: "Clothing type",
	allowClear: true
	});

	$('#colour').select2({
	placeholder: "Colour",
	allowClear: true
	});

	$('#country').select2({
	placeholder: "Country",
	allowClear: true
	});

	url = current_domain + ':9201/garments/_search'

	$.ajax(url, {
            cache: false,
            dataType: 'json',
            type: 'POST',
            success: function (data, status, jqXHR) {
                results = data;
                console.log( results );
                console.log( 'yes' );
                var r_items = [];
                for (var i=0; i<results.hits.hits.length; i++) {
                    r_items.push(results.hits.hits[i]);
                    };

                for (var r=0; r<r_items.length; r++) {
                    if(r_items[r]._source.pic_title) {
                        $('

')
                        .append(
                            $('')
                        )
                        .append(
                            $('
')
                        )
                        .append(
                            $('' + r_items[r]._source.country + '')
                        )
                        .appendTo('#image')

                    }

                };

            $('.image-container img').click(function() {
                alert('yay')
            });

            }
        });

    $('#go').click(function(event) {
        $("#image").html("");
        event.preventDefault();
        console.log('go');
        ct = $('#clothing_type').val()
        cl = $('#colour').val()
        brand = $('#brand').val().toLowerCase();
        country = $('#country').val().toLowerCase();

        data = '{"query":{"filtered":{"query":{"match_all":{}},"filter":{"bool":{"must":['

        if (country) {data = data + '{"term":{"country":"' + country + '"}}'};

        if (cl) {
            if (country) {
                data = data + ',{"term":{"colour":"' + cl + '"}}'
                } else {data = data + '{"term":{"colour":"' + cl + '"}}'}
                };

        if (ct) {
            if (cl || country) {
                data = data + ',{"term":{"clothing_type":"' + ct + '"}}'
                } else {data = data + '{"term":{"clothing_type":"' + ct + '"}}'}
            };

        if (brand) {
            if (cl || ct || country){
                data = data + ',{"term":{"brand":"' + brand + '"}}'
                } else {data = data + '{"term":{"brand":"' + brand + '"}}'}
            };

        /*
        var added_a_term = false;
        if (country) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"country":"' + country + '"}}'
            added_a_term = true
        }

        if (cl) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"colour":"' + cl + '"}}'
            added_a_term = true
        }

        if (ct) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"clothing_type":"' + ct + '"}}'
            added_a_term = true
        }
        */

        data = data + ']}}}}}'
        console.log(data)

        url = current_domain + ':9201/garments/_search'
        var results;
        console.log('go')

        $.ajax(url, {
            cache: false,
            dataType: 'json',
            type: 'POST',
            data: data,
            success: function (data, status, jqXHR) {
                results = data;
                console.log( results );
                console.log( 'yes' );
                var r_items = [];
                for (var i=0; i<results.hits.hits.length; i++) {
                    r_items.push(results.hits.hits[i]);
                    };

                for (var r=0; r<r_items.length; r++) {
                    if(r_items[r]._source.pic_title) {
                        $('

')
                        .append(
                            $('')
                        )
                        .append(
                            $('
')
                        )
                        .append(
                            $('' + r_items[r]._source.country + '')
                        )
                        .appendTo('#image')

                    }

                };

            $('.image-container img').click(function() {
                alert('yay')
            });

            }
        });
    });
});

<commit_msg>Changed AJAX request url<commit_after>$(document).ready(function() {
    $('#clothing_type').select2({
	placeholder: "Clothing type",
	allowClear: true
	});

	$('#colour').select2({
	placeholder: "Colour",
	allowClear: true
	});

	$('#country').select2({
	placeholder: "Country",
	allowClear: true
	});

	url = current_scheme + '//' + current_domain + ':9201/garments/_search'

	$.ajax(url, {
            cache: false,
            dataType: 'json',
            type: 'POST',
            success: function (data, status, jqXHR) {
                results = data;
                console.log( results );
                console.log( 'yes' );
                var r_items = [];
                for (var i=0; i<results.hits.hits.length; i++) {
                    r_items.push(results.hits.hits[i]);
                    };

                for (var r=0; r<r_items.length; r++) {
                    if(r_items[r]._source.pic_title) {
                        $('

')
                        .append(
                            $('')
                        )
                        .append(
                            $('
')
                        )
                        .append(
                            $('' + r_items[r]._source.country + '')
                        )
                        .appendTo('#image')

                    }

                };

            $('.image-container img').click(function() {
                alert('yay')
            });

            }
        });

    $('#go').click(function(event) {
        $("#image").html("");
        event.preventDefault();
        console.log('go');
        ct = $('#clothing_type').val()
        cl = $('#colour').val()
        brand = $('#brand').val().toLowerCase();
        country = $('#country').val().toLowerCase();

        data = '{"query":{"filtered":{"query":{"match_all":{}},"filter":{"bool":{"must":['

        if (country) {data = data + '{"term":{"country":"' + country + '"}}'};

        if (cl) {
            if (country) {
                data = data + ',{"term":{"colour":"' + cl + '"}}'
                } else {data = data + '{"term":{"colour":"' + cl + '"}}'}
                };

        if (ct) {
            if (cl || country) {
                data = data + ',{"term":{"clothing_type":"' + ct + '"}}'
                } else {data = data + '{"term":{"clothing_type":"' + ct + '"}}'}
            };

        if (brand) {
            if (cl || ct || country){
                data = data + ',{"term":{"brand":"' + brand + '"}}'
                } else {data = data + '{"term":{"brand":"' + brand + '"}}'}
            };

        /*
        var added_a_term = false;
        if (country) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"country":"' + country + '"}}'
            added_a_term = true
        }

        if (cl) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"colour":"' + cl + '"}}'
            added_a_term = true
        }

        if (ct) {
            if(added_a_term) { data = data + ',' }
            data = data + '{"term":{"clothing_type":"' + ct + '"}}'
            added_a_term = true
        }
        */

        data = data + ']}}}}}'
        console.log(data)

        url = current_scheme + '//' + current_domain + ':9201/garments/_search'
        var results;
        console.log('go')

        $.ajax(url, {
            cache: false,
            dataType: 'json',
            type: 'POST',
            data: data,
            success: function (data, status, jqXHR) {
                results = data;
                console.log( results );
                console.log( 'yes' );
                var r_items = [];
                for (var i=0; i<results.hits.hits.length; i++) {
                    r_items.push(results.hits.hits[i]);
                    };

                for (var r=0; r<r_items.length; r++) {
                    if(r_items[r]._source.pic_title) {
                        $('

')
                        .append(
                            $('')
                        )
                        .append(
                            $('
')
                        )
                        .append(
                            $('' + r_items[r]._source.country + '')
                        )
                        .appendTo('#image')

                    }

                };

            $('.image-container img').click(function() {
                alert('yay')
            });

            }
        });
    });
});

<|endoftext|>


<commit_before>// List of references to module classes
var moduleList = [tsModuleTest];
<commit_msg>Testing with Multiple Modules<commit_after>// List of references to module classes
//var moduleList = [tsModuleTest];
var moduleList = [tsModuleTest, tsModule];
<|endoftext|>


<commit_before>'use strict';
const curry = require('core.lambda').curry;

function tap(thenFn, promise) {
  return promise.then(function(res) {
    thenFn(res);
    return res;
  });
}
<commit_msg>fixed tap<commit_after>'use strict';
const curry = require('core.lambda').curry;

module.exports = curry(2, tap);

/**
 * For side effects. Run a function on a promise's result, returning original resolution value.
 * @param  {Function} thenFn  Callback for promise's resolution value
 * @param  {Promise} promise Promise to run on
 * @return {Promise}         Promise that resolves to original resolution value
 */
function tap(thenFn, promise) {
  return promise.then(function(res) {
    thenFn(res);
    return res;
  });
}
<|endoftext|>


<commit_before>var STATUS = true;
var FLAG = "";

function updateElems(data){
    timeupdate = ''
    flagupdate = ''
    statusupdate = ''
    STATUS = data.status;
    FLAG = data.flag;
    if(FLAG == 'ON')
    {
        $('#autobutton').css('display','block');
        $('#manualon').css('display','block');
        $('#manualoff').css('display','none');
    }
    else if(FLAG == 'OFF'){
        $('#autobutton').css('display','block');
        $('#manualon').css('display','none');
        $('#manualoff').css('display','block');
    }
    else
    {
        $('#autobutton').css('display','none');
        $('#manualon').css('display','none');
        $('#manualoff').css('display','none');
    }

    if(STATUS == true){
        $('#status').text("Свет включен.");
        $('#ibutton').attr('src', "\\static\\switch-on-button.png");
        $('#abutton').attr('href', "javascript:switchto('OFF');");
    }
    else
    {
        if(STATUS == false){
            $('#status').text("Свет выключен.");
            $('#ibutton').attr('src', "\\static\\switch-off-button.png");
            $('#abutton').attr('href', "javascript:switchto('ON');");
        }
        else
        {
            $('#status').text("Статус не известен."+STATUS);
            $('#ibutton').attr('src', "\\static\\switch-off-button.png");
            $('#abutton').attr('href', "javascript:switchto('ON');");
        }
    }
    $('#timeupdate').text("["+data.time+"]");
    $('#flagupdate').text("["+FLAG+"]");
    $('#statusupdate').text("["+STATUS+"]");
    update();
}

function switchto(status) {
    $.ajax({
        url: '/do?switchto='+status,
        success:  function(data) {
            updateElems(data);
        }
    });
}

/**
 * Request an update to the server and once it has answered, then update
 * the content and request again.
 * The server is supposed to response when a change has been made on data.
 */
function update() {
    $.ajax({
        url: '/status-update?status='+STATUS+"&flag="+FLAG,
        success:  function(data) {
            updateElems(data);
        },
        timeout: function(data) { update(); }//If timeout is reached run again
    });
}

/**
 * Perform first data request. After taking this data, just query the
 * server and refresh when answered (via update call).
 */
function load() {
    $.ajax({
        url: '/status',
        success: function(data) {
            updateElems(data);
        }
    });
}

$(document).ready(function() {
    load();
});<commit_msg>Обновление данных теперь в любом случае (и при таймауте и при ошибке и при получении данных). Установлен таймаут запроса 10 минут Обновление (запро на него) не дулируется теперь при других запросах.<commit_after>var STATUS = true;
var FLAG = "";

function updateElems(data){
    timeupdate = ''
    flagupdate = ''
    statusupdate = ''
    STATUS = data.status;
    FLAG = data.flag;
    if(FLAG == 'ON')
    {
        $('#autobutton').css('display','block');
        $('#manualon').css('display','block');
        $('#manualoff').css('display','none');
    }
    else if(FLAG == 'OFF'){
        $('#autobutton').css('display','block');
        $('#manualon').css('display','none');
        $('#manualoff').css('display','block');
    }
    else
    {
        $('#autobutton').css('display','none');
        $('#manualon').css('display','none');
        $('#manualoff').css('display','none');
    }

    if(STATUS == true){
        $('#status').text("Свет включен.");
        $('#ibutton').attr('src', "\\static\\switch-on-button.png");
        $('#abutton').attr('href', "javascript:switchto('OFF');");
    }
    else
    {
        if(STATUS == false){
            $('#status').text("Свет выключен.");
            $('#ibutton').attr('src', "\\static\\switch-off-button.png");
            $('#abutton').attr('href', "javascript:switchto('ON');");
        }
        else
        {
            $('#status').text("Статус не известен."+STATUS);
            $('#ibutton').attr('src', "\\static\\switch-off-button.png");
            $('#abutton').attr('href', "javascript:switchto('ON');");
        }
    }
    $('#timeupdate').text("["+data.time+"]");
    $('#flagupdate').text("["+FLAG+"]");
    $('#statusupdate').text("["+STATUS+"]");
}

function switchto(status) {
    $.ajax({
        url: '/do?switchto='+status,
        success:  function(data) {
            updateElems(data);
        }
    });
}

/**
 * Request an update to the server and once it has answered, then update
 * the content and request again.
 * The server is supposed to response when a change has been made on data.
 */
function update() {
    $.ajax({
        url: '/status-update?status='+STATUS+"&flag="+FLAG,
        success: function(data) {
            updateElems(data);
        },
        timeout: 600000,//If timeout is reached run again
        error: function(data) {
            //console.log("Error!");
        },
        complete: function(data) {
             update();
        }
    });
}

/**
 * Perform first data request. After taking this data, just query the
 * server and refresh when answered (via update call).
 */
function load() {
    $.ajax({
        url: '/status',
        success: function(data) {
            updateElems(data);
            update();
        }
    });
}

$(document).ready(function() {
    load();
});<|endoftext|>


<commit_before>Meteor.subscribe('reports');
Session.setDefault('easter egg counter', 0);

function getReports() {

  var query = {
    expired: false
  };

  if (viewingFavs()) {
    var favs = getFavs();
    query.line = {
      $in: favs.lines
    };
    query.dir = {
      $in: favs.dirs
    };
  }

  return Reports.find(query, { sort: {createdAt: -1}});
}

Template.now.helpers({
  noReports: function() {
    return getReports().count() === 0;
  },
  reports: getReports
});

Template.now.onRendered(function() {

  var reqAnimationFrame = (function () {
    var raf =  window[Hammer.prefixed(window, 'requestAnimationFrame')];
    return raf || function (callback) {
      window.setTimeout(callback, 1000 / 60);
    };
  })();

  var ninja = document.querySelector("#play-ninja");
  var cover = document.querySelector(".cover");

  var ticking = false;
  var transform;
  var timer;

  var mc = new Hammer.Manager(ninja);

  mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
  mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);

  mc.on("panstart panmove", onPan);
  mc.on("rotatestart rotatemove", onRotate);
  mc.on("pinchstart pinchmove", onPinch);

  mc.on("hammer.input", function(ev) {
    if (ev.isFinal) {
      resetElement();
    }
  });

  function resetElement() {
    ninja.className = 'animate';
    transform = {
      translate: { x: 0, y: 0 },
      scale: 1,
      rotateX: 0,
      rotateY: 0,
      rotateZ: 0,
    };
    requestElementUpdate();
  }

  function updateElementTransform() {
    var value = [
      'translate3d(' + transform.translate.x + 'px, ' +
        transform.translate.y + 'px, 0)',
      'scale(' + transform.scale + ', ' + transform.scale + ')',
      'rotateX('+ transform.rotateX + 'deg)',
      'rotateY('+ transform.rotateY + 'deg)',
      'rotateZ('+ transform.rotateZ + 'deg)',
    ];

    value = value.join(" ");
    ninja.style.webkitTransform = value;
    ninja.style.mozTransform = value;
    ninja.style.transform = value;
    ticking = false;
  }

  function requestElementUpdate() {
    if(!ticking) {
      reqAnimationFrame(updateElementTransform);
      ticking = true;
    }
  }

  var max = Math.min(cover.offsetWidth / 2, cover.offsetHeight / 2);

  function damp(x, max) {
    var abs = max * (1 - Math.exp(-0.005 * Math.abs(x)));
    return x > 0 ? abs : -abs;
  }

  function onPan(ev) {
    ninja.className = '';
    transform.translate = {
      x: damp(ev.deltaX, max),
      y: damp(ev.deltaY, max)
    };

    transform.rotateX = - damp(ev.deltaY, 90);
    transform.rotateY = damp(ev.deltaX, 90);

    requestElementUpdate();
  }

  var initScale = 1;
  function onPinch(ev) {
    if(ev.type == 'pinchstart') {
      initScale = transform.scale || 1;
    }

    ninja.className = '';
    transform.scale = initScale * ev.scale;

    requestElementUpdate();
  }

  var initAngle = 0;
  function onRotate(ev) {
    if(ev.type == 'rotatestart') {
      initAngle = transform.angle || 0;
    }

    ninja.className = '';
    transform.rz = 1;
    transform.angle = initAngle + ev.rotation;

    requestElementUpdate();
  }

  resetElement();

});

Template.now.helpers({
  duzo: function() {
    return Session.get('easter egg counter') > 6;
  },
});

Template.now.events({
    'click .cover': function(event) {
        Session.set('easter egg counter', Session.get('easter egg counter') + 1);
    },
});
<commit_msg>zrobilem jedne helpers<commit_after>Meteor.subscribe('reports');
Session.setDefault('easter egg counter', 0);

function getReports() {

  var query = {
    expired: false
  };

  if (viewingFavs()) {
    var favs = getFavs();
    query.line = {
      $in: favs.lines
    };
    query.dir = {
      $in: favs.dirs
    };
  }

  return Reports.find(query, { sort: {createdAt: -1}});
}

Template.now.helpers({
  noReports: function() {
    return getReports().count() === 0;
  },
  reports: getReports,

  duzo: function() {
    return Session.get('easter egg counter') > 6;
  },
});

Template.now.onRendered(function() {

  var reqAnimationFrame = (function () {
    var raf =  window[Hammer.prefixed(window, 'requestAnimationFrame')];
    return raf || function (callback) {
      window.setTimeout(callback, 1000 / 60);
    };
  })();

  var ninja = document.querySelector("#play-ninja");
  var cover = document.querySelector(".cover");

  var ticking = false;
  var transform;
  var timer;

  var mc = new Hammer.Manager(ninja);

  mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
  mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);

  mc.on("panstart panmove", onPan);
  mc.on("rotatestart rotatemove", onRotate);
  mc.on("pinchstart pinchmove", onPinch);

  mc.on("hammer.input", function(ev) {
    if (ev.isFinal) {
      resetElement();
    }
  });

  function resetElement() {
    ninja.className = 'animate';
    transform = {
      translate: { x: 0, y: 0 },
      scale: 1,
      rotateX: 0,
      rotateY: 0,
      rotateZ: 0,
    };
    requestElementUpdate();
  }

  function updateElementTransform() {
    var value = [
      'translate3d(' + transform.translate.x + 'px, ' +
        transform.translate.y + 'px, 0)',
      'scale(' + transform.scale + ', ' + transform.scale + ')',
      'rotateX('+ transform.rotateX + 'deg)',
      'rotateY('+ transform.rotateY + 'deg)',
      'rotateZ('+ transform.rotateZ + 'deg)',
    ];

    value = value.join(" ");
    ninja.style.webkitTransform = value;
    ninja.style.mozTransform = value;
    ninja.style.transform = value;
    ticking = false;
  }

  function requestElementUpdate() {
    if(!ticking) {
      reqAnimationFrame(updateElementTransform);
      ticking = true;
    }
  }

  var max = Math.min(cover.offsetWidth / 2, cover.offsetHeight / 2);

  function damp(x, max) {
    var abs = max * (1 - Math.exp(-0.005 * Math.abs(x)));
    return x > 0 ? abs : -abs;
  }

  function onPan(ev) {
    ninja.className = '';
    transform.translate = {
      x: damp(ev.deltaX, max),
      y: damp(ev.deltaY, max)
    };

    transform.rotateX = - damp(ev.deltaY, 90);
    transform.rotateY = damp(ev.deltaX, 90);

    requestElementUpdate();
  }

  var initScale = 1;
  function onPinch(ev) {
    if(ev.type == 'pinchstart') {
      initScale = transform.scale || 1;
    }

    ninja.className = '';
    transform.scale = initScale * ev.scale;

    requestElementUpdate();
  }

  var initAngle = 0;
  function onRotate(ev) {
    if(ev.type == 'rotatestart') {
      initAngle = transform.angle || 0;
    }

    ninja.className = '';
    transform.rz = 1;
    transform.angle = initAngle + ev.rotation;

    requestElementUpdate();
  }

  resetElement();

});

Template.now.events({
    'click .cover': function(event) {
        Session.set('easter egg counter', Session.get('easter egg counter') + 1);
    },
});
<|endoftext|>