<commit_before>import Vue from 'vue'

describe('Directive v-model component', () => {
  it('should work', done => {
    const vm = new Vue({
      data: {
        msg: 'hello'
      },
      template: `

{{ msg }}

          <test v-model="msg"></test>

      `,
      components: {
        test: {
          props: ['value'],
          template: `<input :value="value" @input="$emit('input', $event.target.value)">`
        }
      }
    }).$mount()
    document.body.appendChild(vm.$el)
    waitForUpdate(() => {
      const input = vm.$el.querySelector('input')
      input.value = 'world'
      triggerEvent(input, 'input')
    }).then(() => {
      expect(vm.msg).toEqual('world')
      expect(vm.$el.querySelector('p').textContent).toEqual('world')
      vm.msg = 'changed'
    }).then(() => {
      expect(vm.$el.querySelector('p').textContent).toEqual('changed')
      expect(vm.$el.querySelector('input').value).toEqual('changed')
    }).then(() => {
      document.body.removeChild(vm.$el)
    }).then(done)
  })

  it('should support customization via model option', done => {
    const vm = new Vue({
      data: {
        msg: 'hello'
      },
      template: `

{{ msg }}

          <test v-model="msg"></test>

      `,
      components: {
        test: {
          model: {
            prop: 'currentValue',
            event: 'update'
          },
          props: ['currentValue'],
          template: `<input :value="currentValue" @input="$emit('update', $event.target.value)">`
        }
      }
    }).$mount()
    document.body.appendChild(vm.$el)
    waitForUpdate(() => {
      const input = vm.$el.querySelector('input')
      input.value = 'world'
      triggerEvent(input, 'input')
    }).then(() => {
      expect(vm.msg).toEqual('world')
      expect(vm.$el.querySelector('p').textContent).toEqual('world')
      vm.msg = 'changed'
    }).then(() => {
      expect(vm.$el.querySelector('p').textContent).toEqual('changed')
      expect(vm.$el.querySelector('input').value).toEqual('changed')
    }).then(() => {
      document.body.removeChild(vm.$el)
    }).then(done)
  })

  it('modifier: .number', () => {
    const vm = new Vue({
      template: `<div><my-input ref="input" v-model.number="text"></my-input></div>`,
      data: { text: 'foo' },
      components: {
        'my-input': {
          template: '<input>'
        }
      }
    }).$mount()
    expect(vm.text).toBe('foo')
    vm.$refs.input.$emit('input', 'bar')
    expect(vm.text).toBe('bar')
    vm.$refs.input.$emit('input', '123')
    expect(vm.text).toBe(123)
  })

  it('modifier: .trim', () => {
    const vm = new Vue({
      template: `<div><my-input ref="input" v-model.trim="text"></my-input></div>`,
      data: { text: 'foo' },
      components: {
        'my-input': {
          template: '<input>'
        }
      }
    }).$mount()
    expect(vm.text).toBe('foo')
    vm.$refs.input.$emit('input', '  bar  ')
    expect(vm.text).toBe('bar')
    vm.$refs.input.$emit('input', '   foo o  ')
    expect(vm.text).toBe('foo o')
  })
})
<commit_msg>complete coverage by testing v-model with extra listeners<commit_after>import Vue from 'vue'

describe('Directive v-model component', () => {
  it('should work', done => {
    const vm = new Vue({
      data: {
        msg: 'hello'
      },
      template: `

{{ msg }}

          <test v-model="msg"></test>

      `,
      components: {
        test: {
          props: ['value'],
          template: `<input :value="value" @input="$emit('input', $event.target.value)">`
        }
      }
    }).$mount()
    document.body.appendChild(vm.$el)
    waitForUpdate(() => {
      const input = vm.$el.querySelector('input')
      input.value = 'world'
      triggerEvent(input, 'input')
    }).then(() => {
      expect(vm.msg).toEqual('world')
      expect(vm.$el.querySelector('p').textContent).toEqual('world')
      vm.msg = 'changed'
    }).then(() => {
      expect(vm.$el.querySelector('p').textContent).toEqual('changed')
      expect(vm.$el.querySelector('input').value).toEqual('changed')
    }).then(() => {
      document.body.removeChild(vm.$el)
    }).then(done)
  })

  it('should support customization via model option', done => {
    const spy = jasmine.createSpy('update')
    const vm = new Vue({
      data: {
        msg: 'hello'
      },
      methods: {
        spy
      },
      template: `

{{ msg }}

          <test v-model="msg" @update="spy"></test>

      `,
      components: {
        test: {
          model: {
            prop: 'currentValue',
            event: 'update'
          },
          props: ['currentValue'],
          template: `<input :value="currentValue" @input="$emit('update', $event.target.value)">`
        }
      }
    }).$mount()
    document.body.appendChild(vm.$el)
    waitForUpdate(() => {
      const input = vm.$el.querySelector('input')
      input.value = 'world'
      triggerEvent(input, 'input')
    }).then(() => {
      expect(vm.msg).toEqual('world')
      expect(vm.$el.querySelector('p').textContent).toEqual('world')
      expect(spy).toHaveBeenCalledWith('world')
      vm.msg = 'changed'
    }).then(() => {
      expect(vm.$el.querySelector('p').textContent).toEqual('changed')
      expect(vm.$el.querySelector('input').value).toEqual('changed')
    }).then(() => {
      document.body.removeChild(vm.$el)
    }).then(done)
  })

  it('modifier: .number', () => {
    const vm = new Vue({
      template: `<div><my-input ref="input" v-model.number="text"></my-input></div>`,
      data: { text: 'foo' },
      components: {
        'my-input': {
          template: '<input>'
        }
      }
    }).$mount()
    expect(vm.text).toBe('foo')
    vm.$refs.input.$emit('input', 'bar')
    expect(vm.text).toBe('bar')
    vm.$refs.input.$emit('input', '123')
    expect(vm.text).toBe(123)
  })

  it('modifier: .trim', () => {
    const vm = new Vue({
      template: `<div><my-input ref="input" v-model.trim="text"></my-input></div>`,
      data: { text: 'foo' },
      components: {
        'my-input': {
          template: '<input>'
        }
      }
    }).$mount()
    expect(vm.text).toBe('foo')
    vm.$refs.input.$emit('input', '  bar  ')
    expect(vm.text).toBe('bar')
    vm.$refs.input.$emit('input', '   foo o  ')
    expect(vm.text).toBe('foo o')
  })
})
<|endoftext|>


<commit_before>'use strict'

const Joi = require('joi')
const { BaseXmlService } = require('..')
const { renderVersionBadge } = require('../version')

const schema = Joi.object({
  metadata: Joi.object({
    versioning: Joi.object({
      versions: Joi.object({
        version: Joi.array()
          .items(
            Joi.alternatives(Joi.string().required(), Joi.number().required())
          )
          .required(),
      }).required(),
    }).required(),
  }).required(),
}).required()

module.exports = class MavenMetadata extends BaseXmlService {
  static get category() {
    return 'version'
  }

  static get route() {
    return {
      base: 'maven-metadata/v',
      pattern: ':protocol(http|https)/:hostAndPath+',
    }
  }

  static get examples() {
    return [
      {
        title: 'Maven metadata URL',
        namedParams: {
          protocol: 'http',
          hostAndPath:
            'central.maven.org/maven2/com/google/code/gson/gson/maven-metadata.xml',
        },
        staticPreview: renderVersionBadge({ version: '2.8.5' }),
      },
    ]
  }

  static get defaultBadgeData() {
    return { label: 'maven' }
  }

  async fetch({ protocol, hostAndPath }) {
    const url = `${protocol}://${hostAndPath}`
    return this._requestXml({ schema, url })
  }

  async handle({ protocol, hostAndPath }) {
    const data = await this.fetch({ protocol, hostAndPath })
    return renderVersionBadge({
      version: data.metadata.versioning.versions.version.slice(-1)[0],
    })
  }
}
<commit_msg>fix(maven-metadata): update schema to support single published versions (#3182)<commit_after>'use strict'

const Joi = require('joi')
const { BaseXmlService } = require('..')
const { renderVersionBadge } = require('../version')

const schema = Joi.object({
  metadata: Joi.object({
    versioning: Joi.object({
      versions: Joi.object({
        version: Joi.array()
          .items(
            Joi.alternatives(Joi.string().required(), Joi.number().required())
          )
          .single()
          .required(),
      }).required(),
    }).required(),
  }).required(),
}).required()

module.exports = class MavenMetadata extends BaseXmlService {
  static get category() {
    return 'version'
  }

  static get route() {
    return {
      base: 'maven-metadata/v',
      pattern: ':protocol(http|https)/:hostAndPath+',
    }
  }

  static get examples() {
    return [
      {
        title: 'Maven metadata URL',
        namedParams: {
          protocol: 'http',
          hostAndPath:
            'central.maven.org/maven2/com/google/code/gson/gson/maven-metadata.xml',
        },
        staticPreview: renderVersionBadge({ version: '2.8.5' }),
      },
    ]
  }

  static get defaultBadgeData() {
    return { label: 'maven' }
  }

  async fetch({ protocol, hostAndPath }) {
    const url = `${protocol}://${hostAndPath}`
    return this._requestXml({ schema, url })
  }

  async handle({ protocol, hostAndPath }) {
    const data = await this.fetch({ protocol, hostAndPath })
    return renderVersionBadge({
      version: data.metadata.versioning.versions.version.slice(-1)[0],
    })
  }
}
<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

(function(global, slice)
{
  var bind = function(func, context)
  {
    // Inspired by: http://webreflection.blogspot.de/2012/11/my-name-is-bound-method-bound.html

    if (jasy.Env.isSet("debug"))
    {
      core.Assert.isType(func, "Function");
      core.Assert.isType(context, "Object");
    }

    // Using name which is not common to store these references in their objects
    // Storing it on the object has the benefit that when the object is
    // garbage collected its bound methods are gone as well.
    var boundName = "bound:" + core.util.Id.get(func);

    return context[boundName] || (
      context[boundName] = func.bind(context)
    );
  };

  var createDelayed = function(nativeMethod)
  {
    return function(callback, context, delay, args)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(callback, "Function");
        core.Assert.isType(context, "Object");
        core.Assert.isType(delay, "Integer");
      }

      if (arguments.length > 3)
      {
        if (!context) {
          context = global;
        }

        var callbackArgs = slice.call(arguments, 3);

        return nativeMethod(function() {
          callback.apply(context, callbackArgs);
        }, delay);
      }
      else
      {
        if (context) {
          callback = bind(callback, context);
        }

        return nativeMethod(callback, delay);
      }
    }
  };

  var immediate;

  // Try NodeJS style nextTick() API
  // http://howtonode.org/understanding-process-next-tick
  if (global.process && process.nextTick)
  {
    immediate = process.nextTick;
  }
  else
  {
    // Try experimental setImmediate() API
    // https://developer.mozilla.org/en-US/docs/DOM/window.setImmediate
    immediate = core.util.Experimental.get(global, "setImmediate");

    if (immediate)
    {
      immediate = global[immediate];
    }
    else
    {
      // Last fallback: Timeout
      immediate = function(func) {
        return setTimeout(func, 0);
      };
    }
  }

  /**
   * A collection of utility methods for native JavaScript functions.
   */
  core.Module("core.Function",
  {
    /**
     * {Function} Binds the given function @func {Function} to the given @object {Object} and returns
     * the resulting function.
     *
     * - Only one connection is made to allow proper disconnecting without access to the bound function.
     * - Uses ES5 bind() to connect functions to objects internally.
     */
    bind : bind,

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * after a timeout of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    timeout : createDelayed(setTimeout),

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * every interval of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    interval : createDelayed(setInterval),

    /**
     * {Function} Debounces the given method.
     *
     * Debouncing ensures that exactly one signal is sent for an event that may be happening
     * several times — or even several hundreds of times over an extended period. As long as
     * the events are occurring fast enough to happen at least once in every detection
     * period, the signal will not be sent!
     *
     * - @threshold {Integer?100} Number of milliseconds of distance required before reacting/resetting.
     * - @execAsap {Boolean?false} Whether the execution should happen at begin.
     */
    debounce : function(func, threshold, execAsap)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (threshold != null) {
          core.Assert.isType(threshold, "Integer");
        }

        if (execAsap != null) {
          core.Assert.isType(execAsap, "Boolean");
        }
      }

      // Via: http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
      var timeout;

      return function()
      {
        var obj = this, args = arguments;
        function delayed()
        {
          if (!execAsap) {
            func.apply(obj, args);
          }

          timeout = null;
        };

        if (timeout){
          clearTimeout(timeout);
        } else if (execAsap) {
          func.apply(obj, args);
        }

        timeout = setTimeout(delayed, threshold || 100);
      };
    },

    /**
     * {Function} Returns a new function that when called multiple times will only call the
     * original function after the specificed @time {Integer} in milliseconds has elapsed.
     */
    throttle : function(func, time)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
        core.Assert.isType(time, "Integer");
      }

      var lastEventTimestamp = null;
      var limit = time;

      return function()
      {
        var self = this;
        var args = arguments;
        var now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit)
        {
          lastEventTimestamp = now;
          func.apply(self, args);
        }
      };
    },

    /**
     * Executes the given @func {Function} immediately, but not in the current
     * thread (non-blocking). Optionally is able to call the method in the given
     * @context {Object?}.
     */
    immediate : function(func, context)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (context != null) {
          core.Assert.isType(context, "Object");
        }
      }

      if (context) {
        func = bind(func, context);
      }

      immediate(func);
    },

    /**
     * {Function} Returns a new function that curries all given arguments to the given @func {Function}.
     */
    curry : function(func) {
      var args = core.Array.fromArguments(arguments);
      args.splice(0, 1);
      return function() {
        return func.apply(this, args.concat(core.Array.fromArguments(arguments)));
      };
    }
  });
})(core.Main.getGlobal(), Array.prototype.slice);
<commit_msg>Add asserts in debug mode<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

(function(global, slice)
{
  var bind = function(func, context)
  {
    // Inspired by: http://webreflection.blogspot.de/2012/11/my-name-is-bound-method-bound.html

    if (jasy.Env.isSet("debug"))
    {
      core.Assert.isType(func, "Function");
      core.Assert.isType(context, "Object");
    }

    // Using name which is not common to store these references in their objects
    // Storing it on the object has the benefit that when the object is
    // garbage collected its bound methods are gone as well.
    var boundName = "bound:" + core.util.Id.get(func);

    return context[boundName] || (
      context[boundName] = func.bind(context)
    );
  };

  var createDelayed = function(nativeMethod)
  {
    return function(callback, context, delay, args)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(callback, "Function");
        core.Assert.isType(context, "Object");
        core.Assert.isType(delay, "Integer");
      }

      if (arguments.length > 3)
      {
        if (!context) {
          context = global;
        }

        var callbackArgs = slice.call(arguments, 3);

        return nativeMethod(function() {
          callback.apply(context, callbackArgs);
        }, delay);
      }
      else
      {
        if (context) {
          callback = bind(callback, context);
        }

        return nativeMethod(callback, delay);
      }
    }
  };

  var immediate;

  // Try NodeJS style nextTick() API
  // http://howtonode.org/understanding-process-next-tick
  if (global.process && process.nextTick)
  {
    immediate = process.nextTick;
  }
  else
  {
    // Try experimental setImmediate() API
    // https://developer.mozilla.org/en-US/docs/DOM/window.setImmediate
    immediate = core.util.Experimental.get(global, "setImmediate");

    if (immediate)
    {
      immediate = global[immediate];
    }
    else
    {
      // Last fallback: Timeout
      immediate = function(func) {
        return setTimeout(func, 0);
      };
    }
  }

  /**
   * A collection of utility methods for native JavaScript functions.
   */
  core.Module("core.Function",
  {
    /**
     * {Function} Binds the given function @func {Function} to the given @object {Object} and returns
     * the resulting function.
     *
     * - Only one connection is made to allow proper disconnecting without access to the bound function.
     * - Uses ES5 bind() to connect functions to objects internally.
     */
    bind : bind,

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * after a timeout of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    timeout : createDelayed(setTimeout),

    /**
     * {Number} Executes the given @callback {Function} in the given @context {Object?global}
     * every interval of @delay {Number} milliseconds. Supports optional
     * @args {arguments...} which are passed to the @callback.
     */
    interval : createDelayed(setInterval),

    /**
     * {Function} Debounces the given method.
     *
     * Debouncing ensures that exactly one signal is sent for an event that may be happening
     * several times — or even several hundreds of times over an extended period. As long as
     * the events are occurring fast enough to happen at least once in every detection
     * period, the signal will not be sent!
     *
     * - @threshold {Integer?100} Number of milliseconds of distance required before reacting/resetting.
     * - @execAsap {Boolean?false} Whether the execution should happen at begin.
     */
    debounce : function(func, threshold, execAsap)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (threshold != null) {
          core.Assert.isType(threshold, "Integer");
        }

        if (execAsap != null) {
          core.Assert.isType(execAsap, "Boolean");
        }
      }

      // Via: http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
      var timeout;

      return function()
      {
        var obj = this, args = arguments;
        function delayed()
        {
          if (!execAsap) {
            func.apply(obj, args);
          }

          timeout = null;
        };

        if (timeout){
          clearTimeout(timeout);
        } else if (execAsap) {
          func.apply(obj, args);
        }

        timeout = setTimeout(delayed, threshold || 100);
      };
    },

    /**
     * {Function} Returns a new function that when called multiple times will only call the
     * original function after the specificed @time {Integer} in milliseconds has elapsed.
     */
    throttle : function(func, time)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
        core.Assert.isType(time, "Integer");
      }

      var lastEventTimestamp = null;
      var limit = time;

      return function()
      {
        var self = this;
        var args = arguments;
        var now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit)
        {
          lastEventTimestamp = now;
          func.apply(self, args);
        }
      };
    },

    /**
     * Executes the given @func {Function} immediately, but not in the current
     * thread (non-blocking). Optionally is able to call the method in the given
     * @context {Object?}.
     */
    immediate : function(func, context)
    {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");

        if (context != null) {
          core.Assert.isType(context, "Object");
        }
      }

      if (context) {
        func = bind(func, context);
      }

      immediate(func);
    },

    /**
     * {Function} Returns a new function that curries all given arguments to the given @func {Function}.
     */
    curry : function(func) {
      if (jasy.Env.isSet("debug"))
      {
        core.Assert.isType(func, "Function");
      }

      var args = core.Array.fromArguments(arguments);
      args.splice(0, 1);
      return function() {
        return func.apply(this, args.concat(core.Array.fromArguments(arguments)));
      };
    }
  });
})(core.Main.getGlobal(), Array.prototype.slice);
<|endoftext|>


<commit_before>export default {
    methods: {
        goToPath: function (path) {
            if (path) {
                this.$router.push({path});
            } else {
                this.goToHomePage();
            }
        },
        goToHomePage: function () {
            this.$router.push({name: "home"});
        },
        goToSignInPage: function () {
            this.$router.push({name: "sign-in"});
        },
        goToPhotoPage: function (id) {
            this.$router.push({
                name: "photo",
                params: {id},
                query: {
                    tag: this.$route.params.tag || this.$route.query.tag,
                    search_phrase: this.$route.params.search_phrase || this.$route.query.search_phrase,
                    page: this.$route.params.page || this.$route.query.page,
                },
            });
        },
        goToPhotosPage: function (id) {
            const withPageSuffix = "-with-page";
            let name = "photos";
            if (this.$route.query.tag) {
                name = "photos-tag";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            } else if (this.$route.query.search_phrase) {
                name = "photos-search";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            } else {
                name = "photos";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            }
            const params = this.$route.query;
            let hash = this.$route.hash;
            if (id) {
                hash = `#gallery-image-${id}`;
            }
            this.$router.push({name, params, hash});
        },
        goToNotFoundPage: function () {
            this.$router.push({name: "404"});
        },
    },
}
<commit_msg>Fixed URL's issue in google analytics<commit_after>import {isDefined} from "tooleks";

export default {
    methods: {
        goToPath: function (path) {
            if (path) {
                this.$router.push({path});
            } else {
                this.goToHomePage();
            }
        },
        goToHomePage: function () {
            this.$router.push({name: "home"});
        },
        goToSignInPage: function () {
            this.$router.push({name: "sign-in"});
        },
        goToPhotoPage: function (id) {
            const query = {
                tag: this.$route.params.tag || this.$route.query.tag,
                search_phrase: this.$route.params.search_phrase || this.$route.query.search_phrase,
                page: this.$route.params.page || this.$route.query.page,
            };
            this.$router.push({
                name: "photo",
                params: {id},
                query: query.filter((param) => isDefined(param)),
            });
        },
        goToPhotosPage: function (id) {
            const withPageSuffix = "-with-page";
            let name = "photos";
            if (this.$route.query.tag) {
                name = "photos-tag";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            } else if (this.$route.query.search_phrase) {
                name = "photos-search";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            } else {
                name = "photos";
                if (this.$route.query.page) {
                    name = name + withPageSuffix;
                }
            }
            const params = this.$route.query;
            let hash = this.$route.hash;
            if (id) {
                hash = `#gallery-image-${id}`;
            }
            this.$router.push({name, params, hash});
        },
        goToNotFoundPage: function () {
            this.$router.push({name: "404"});
        },
    },
}
<|endoftext|>


<commit_before>define([
    '/api/config?cb=' + Math.random().toString(16).substring(2),
    '/common/realtime-textarea.js',
    '/common/messages.js',
    '/common/crypto.js',
    '/bower_components/jquery/dist/jquery.min.js',
    '/customize/pad.js'
], function (Config, Realtime, Messages, Crypto) {
    var $ = window.jQuery;
    $(window).on('hashchange', function() {
        window.location.reload();
    });
    if (window.location.href.indexOf('#') === -1) {
        window.location.href = window.location.href + '#' + Crypto.genKey();
        return;
    }

    var key = Crypto.parseKey(window.location.hash.substring(1));
    var initializing = true;
    var $textarea = $('textarea');

    var config = {
        textarea: $textarea[0],
        websocketURL: Config.websocketURL,
        userName: Crypto.rand64(8),
        channel: key.channel,
        cryptKey: key.cryptKey
    };

    var onInit = config.onInit = function (info) { };

    var onRemote = config.onRemote = function (contents) {
        if (initializing) { return; }
        // TODO...
    };

    var onReady = config.onReady = function (info) {
        initializing = false;
        $textarea.attr('disabled', false);
    };

    var onAbort = config.onAbort = function (info) {
        $textarea.attr('disabled', true);
        window.alert("Server Connection Lost");
    };

    var rt = Realtime.start(config);
});
<commit_msg>repair /text/ application, conform to new API<commit_after>define([
    '/api/config?cb=' + Math.random().toString(16).substring(2),
    '/common/RealtimeTextarea.js',
    '/common/messages.js',
    '/common/crypto.js',
    '/common/TextPatcher.js',
    '/bower_components/jquery/dist/jquery.min.js',
    '/customize/pad.js'
], function (Config, Realtime, Messages, Crypto, TextPatcher) {
    var $ = window.jQuery;
    $(window).on('hashchange', function() {
        window.location.reload();
    });
    if (window.location.href.indexOf('#') === -1) {
        window.location.href = window.location.href + '#' + Crypto.genKey();
        return;
    }

    var module = window.APP = {};
    var key = Crypto.parseKey(window.location.hash.substring(1));
    var initializing = true;
    var $textarea = $('textarea');

    var config = module.config = {
        textarea: $textarea[0],
        websocketURL: Config.websocketURL + '_old',
        userName: Crypto.rand64(8),
        channel: key.channel,
        cryptKey: key.cryptKey
    };

    var setEditable = function (bool) { $textarea.attr('disabled', !bool); };
    var canonicalize = function (text) { return text.replace(/\r\n/g, '\n'); };

    setEditable(false);

    var onInit = config.onInit = function (info) { };

    var onRemote = config.onRemote = function (info) {
        if (initializing) { return; }
        var userDoc = module.realtime.getUserDoc();
        var content = canonicalize($textarea.val());

        var op = TextPatcher.diff(content, userDoc);
        var elem = $textarea[0];

        var selects = ['selectionStart', 'selectionEnd'].map(function (attr) {
            return TextPatcher.transformCursor(elem[attr], op);
        });

        $textarea.val(userDoc);
        elem.selectionStart = selects[0];
        elem.selectionEnd = selects[1];
    };

    var onLocal = config.onLocal = function () {
        if (initializing) { return; }
        module.patchText(canonicalize($textarea.val()));
    };

    var onReady = config.onReady = function (info) {
        var realtime = module.realtime = info.realtime;
        module.patchText = TextPatcher.create({
            realtime: realtime
        });

        $textarea.val(realtime.getUserDoc());

        setEditable(true);
        initializing = false;
    };

    var onAbort = config.onAbort = function (info) {
        $textarea.attr('disabled', true);
        window.alert("Server Connection Lost");
    };

    var rt = Realtime.start(config);

    ['cut', 'paste', 'change', 'keyup', 'keydown', 'select', 'textInput']
        .forEach(function (evt) {
            $textarea.on(evt, onLocal);
        });
});
<|endoftext|>


<commit_before>//@ sourceURL=gputop-ui.js

/*
 * GPU Top
 *
 * Copyright (C) 2015-2016 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

function GputopUI () {
    this.graph_array = [];
    this.graph_options = {
        grid: {
            borderWidth: 1,
            minBorderMargin: 20,
            labelMargin: 10,
            backgroundColor: {
                colors: ["#fff", "#e4f4f4"]
            },
            margin: {
                top: 8,
                bottom: 20,
                left: 20
            },
            // dont know what this is for?!
            markings: function(axes) {
                var markings = [];
                var xaxis = axes.xaxis;
                for (var x = Math.floor(xaxis.min); x < xaxis.max; x += xaxis.tickSize * 2) {
                    markings.push({ xaxis: { from: x, to: x + xaxis.tickSize }, color: "rgba(232, 232, 255, 0.2)" });
                }
                return markings;
            }
        },
        xaxis: {
            show: true,
            min: 0,
            max: 1000
        },
        yaxis: {
            min: 0,
            max: 110
        },
        legend: {
            show: true
        }
    };// options

    this.series = [{
        lines: {
            fill: true
        },
        color: "#6666ff"
    }];

    this.start_timestamp = 0;
    this.start_gpu_timestamp = 0;

}

GputopUI.prototype.update_slider_period = function(period_) {
    slider.setValue(period_);
}

GputopUI.prototype.display_graph = function(timestamp) {
    for (var i = 0; i < this.graph_array.length; ++i) {
        var container = "#" + this.graph_array[i];
        var counter = $(container).data("counter");

        var length = counter.updates.length;
        var x_min = 0;
        var x_max = 1;

        if (!this.start_timestamp && length > 0) {
            this.start_timestamp = timestamp;
            this.start_gpu_timestamp = counter.updates[length - 1][0]; // end_timestamp
        }

        var elapsed = (timestamp - this.start_timestamp) * 1000000; // elapsed time from the very begining

        x_max = this.start_gpu_timestamp + elapsed;
        x_min = x_max - 10000000000; // 10 seconds time interval

        // remove the older than 10 seconds samples from the graph data
        for (var j = 0; j < counter.graph_data.length &&
            counter.graph_data[j][0] < (x_min / 100000) - 10000; j++) {}
        if (j > 0)
            counter.graph_data = counter.graph_data.slice(j);

        var save_index = -1;
        for (var j = 0; j < length; j++) {
            var start = counter.updates[j][0];
            var end = counter.updates[j][1];
            var val = counter.updates[j][2]; // value
            counter.graph_data.push([start / 100000, val]);
            save_index = j;
        }

        // resync the timestamps (the javascript timestamp with the counter timestamp)
        if (elapsed > 5000000000 && save_index > -1)
        {
            this.start_timestamp = timestamp;
            this.start_gpu_timestamp = counter.updates[save_index][0];
        }

        // adjust the min and max (start and end of the graph)
        this.graph_options.xaxis.min = (x_min / 100000);
        this.graph_options.xaxis.max = (x_max / 100000) - (gputop.period * 1.5 / 100000);
        this.series[0].data = counter.graph_data;
        $.plot(container, this.series, this.graph_options);

        // remove all the samples from the updates array
        counter.updates.splice(0, counter.updates.length);
    }
}

GputopUI.prototype.display_counter = function(counter) {
    if (counter.invalidate_ == false)
        return;

    if (counter.data_.length == 0)
        return;

    var delta = counter.data_.shift();
    var d_value = counter.data_.shift();
    var max = counter.data_.shift();

    if (counter.div_ == undefined)
        counter.div_ = $('#'+counter.div_bar_id_ );

    if (counter.div_txt_ == undefined)
        counter.div_txt_ = $('#'+counter.div_txt_id_ );

    if (max != 0) {
        var value = 100 * d_value / max;
        counter.div_.css("width", value + "%");
        counter.div_txt_.text(value.toFixed(2));// + " " +counter.samples_);

    } else {
        counter.div_txt_.text(d_value.toFixed(0));// + " " +counter.samples_);
        counter.div_.css("width", "0%");
    }
}

GputopUI.prototype.render_bars = function() {
    window.requestAnimationFrame(gputop_ui.window_render_animation_bars);
    // add support for render graphs as well
}

GputopUI.prototype.window_render_animation_bars = function(timestamp) {
    var metric = gputop.query_active_;
    if (metric == undefined)
        return;

    gputop_ui.display_graph(timestamp);

    window.requestAnimationFrame(gputop_ui.window_render_animation_bars);

    for (var i = 0, l = metric.emc_counters_.length; i < l; i++) {
        var counter = metric.emc_counters_[i];
        gputop_ui.display_counter(counter);
    }
}

GputopUI.prototype.metric_not_supported = function(metric) {
    alert(" Metric not supported " + metric.title_)
}

GputopUI.prototype.display_features = function(features) {
    if (features.devinfo.get_devid() == 0 ) {
        gputop_ui.show_alert(" No device was detected, is it the functionality on kernel ? ","alert-danger");
    }

    $( "#gputop-gpu" ).html( gputop.get_arch_pretty_name() );

    $( ".gputop-connecting" ).hide();
    $( "#gputop-cpu" ).html( features.get_cpu_model() );
    $( "#gputop-kernel-build" ).html( features.get_kernel_build() );
    $( "#gputop-kernel-release" ).html( features.get_kernel_release() );
    $( "#gputop-n-cpus" ).html( features.get_n_cpus() );
    $( "#gputop-kernel-performance-query" ).html( features.get_has_gl_performance_query() );
    $( "#gputop-kernel-performance-i915-oa" ).html( features.get_has_i915_oa() );

    $( "#gputop-n-eus" ).html( features.devinfo.get_n_eus().toInt() );
    $( "#gputop-n-eus-slices" ).html( features.devinfo.get_n_eu_slices().toInt()  );
    $( "#gputop-n-eu-threads-count" ).html( features.devinfo.get_eu_threads_count().toInt()  );

    if (features.get_fake_mode())
        $( "#metrics-tab-a" ).html("Metrics (Fake Mode) ");
}

// types of alerts: alert-success alert-info alert-warning alert-danger
GputopUI.prototype.show_alert = function(message,alerttype){

    var dimiss_time = 5000;
    if (alerttype == "alert-success") dimiss_time = 2500; else
    if (alerttype == "alert-info") dimiss_time = 3500; else
    if (alerttype == "alert-danger") dimiss_time = 30000;

    $('#alert_placeholder').append('
×'+message+'
')
        setTimeout(function() { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
            $("#alertdiv").remove();
        }, dimiss_time);
}

GputopUI.prototype.log = function(log_level, log_message){
    var color = "red";
    switch(log_level) {
        case 0: color = "orange"; break;
        case 1: color = "green"; break;
        case 2: color = "yellow"; break;
        case 3: color = "blue"; break;
        case 4: color = "black"; break;
    }
    $('#editor').append(""+log_message+"
");
}

GputopUI.prototype.syslog = function(message){
    log.value += message + "\n";
}

GputopUI.prototype.weblog = function(message){
    //log.value += message + "\n";
}

GputopUI.prototype.init_interface = function(){
    $( "#gputop-overview-panel" ).load( "ajax/overview.html", function() {
        console.log('gputop-overview-panel load');
        gputop.connect();
    });
}

GputopUI.prototype.load_metrics_panel = function(callback_success) {
    $( '#pane2' ).load( "ajax/metrics.html", function() {
        console.log('Metrics panel loaded');
        callback_success();
    });
}

var gputop_ui = new GputopUI();

GputopUI.prototype.btn_close_current_query = function() {
    var active_query = gputop.query_active_;
    if (active_query==undefined) {
        gputop_ui.show_alert(" No Active Query","alert-info");
        return;
    }

    gputop.close_oa_query(active_query.oa_query_id_, function() {
       gputop_ui.show_alert(" Success closing query","alert-info");
    });
}

GputopUI.prototype.update_process = function(process) {

    var pid = process.pid_;
    var name = process.process_name_;

    var tooltip = ''+ pid + ' ' +name+ '';

    $("#sidebar_processes_info").append('
' + tooltip + '
');
    $('#pid_'+pid).click(function (e) {
        console.log("click "+e.target.id);
    });
}

GputopUI.prototype.btn_get_process_info = function() {
    bootbox.prompt("Process Id?", function(result) {
        if (result === null) {
            gputop_ui.show_alert(" Cancelled","alert-info");
        } else {
            var pid = parseInt(result,10);
            if (!isNaN(pid)) {
                gputop.get_process_info(pid, function(msg) {
                    gputop_ui.show_alert(" Callback "+result,"alert-info");
                });
            } else {
                gputop_ui.show_alert("Input not a valid PID","alert-info");
            }
        }
    });
}

// jquery code
$( document ).ready(function() {
    //log = $( "#log" );
    log = document.getElementById("log");

/*
    $( "#gputop-entries" ).append( '
Close Query
' );
    $( '#close_query' ).click( gputop_ui.btn_close_current_query);
*/

    $( '#process-tab-a' ).click(gputop_ui.btn_get_process_info);

    gputop_ui.init_interface();
    $( '#editor' ).wysiwyg();

    // Display tooltips
    $( '[data-toggle="tooltip"]' ).tooltip();
});
<commit_msg>gputop-ui: Loading SKl metrics in demo mode<commit_after>//@ sourceURL=gputop-ui.js

/*
 * GPU Top
 *
 * Copyright (C) 2015-2016 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

function GputopUI () {
    this.graph_array = [];
    this.graph_options = {
        grid: {
            borderWidth: 1,
            minBorderMargin: 20,
            labelMargin: 10,
            backgroundColor: {
                colors: ["#fff", "#e4f4f4"]
            },
            margin: {
                top: 8,
                bottom: 20,
                left: 20
            },
            // dont know what this is for?!
            markings: function(axes) {
                var markings = [];
                var xaxis = axes.xaxis;
                for (var x = Math.floor(xaxis.min); x < xaxis.max; x += xaxis.tickSize * 2) {
                    markings.push({ xaxis: { from: x, to: x + xaxis.tickSize }, color: "rgba(232, 232, 255, 0.2)" });
                }
                return markings;
            }
        },
        xaxis: {
            show: true,
            min: 0,
            max: 1000
        },
        yaxis: {
            min: 0,
            max: 110
        },
        legend: {
            show: true
        }
    };// options

    this.series = [{
        lines: {
            fill: true
        },
        color: "#6666ff"
    }];

    this.start_timestamp = 0;
    this.start_gpu_timestamp = 0;

}

GputopUI.prototype.update_slider_period = function(period_) {
    slider.setValue(period_);
}

GputopUI.prototype.display_graph = function(timestamp) {
    for (var i = 0; i < this.graph_array.length; ++i) {
        var container = "#" + this.graph_array[i];
        var counter = $(container).data("counter");

        var length = counter.updates.length;
        var x_min = 0;
        var x_max = 1;

        if (!this.start_timestamp && length > 0) {
            this.start_timestamp = timestamp;
            this.start_gpu_timestamp = counter.updates[length - 1][0]; // end_timestamp
        }

        var elapsed = (timestamp - this.start_timestamp) * 1000000; // elapsed time from the very begining

        x_max = this.start_gpu_timestamp + elapsed;
        x_min = x_max - 10000000000; // 10 seconds time interval

        // remove the older than 10 seconds samples from the graph data
        for (var j = 0; j < counter.graph_data.length &&
            counter.graph_data[j][0] < (x_min / 100000) - 10000; j++) {}
        if (j > 0)
            counter.graph_data = counter.graph_data.slice(j);

        var save_index = -1;
        for (var j = 0; j < length; j++) {
            var start = counter.updates[j][0];
            var end = counter.updates[j][1];
            var val = counter.updates[j][2]; // value
            counter.graph_data.push([start / 100000, val]);
            save_index = j;
        }

        // resync the timestamps (the javascript timestamp with the counter timestamp)
        if (elapsed > 5000000000 && save_index > -1)
        {
            this.start_timestamp = timestamp;
            this.start_gpu_timestamp = counter.updates[save_index][0];
        }

        // adjust the min and max (start and end of the graph)
        this.graph_options.xaxis.min = (x_min / 100000);
        this.graph_options.xaxis.max = (x_max / 100000) - (gputop.period * 1.5 / 100000);
        this.series[0].data = counter.graph_data;
        $.plot(container, this.series, this.graph_options);

        // remove all the samples from the updates array
        counter.updates.splice(0, counter.updates.length);
    }
}

GputopUI.prototype.display_counter = function(counter) {
    if (counter.invalidate_ == false)
        return;

    if (counter.data_.length == 0)
        return;

    var delta = counter.data_.shift();
    var d_value = counter.data_.shift();
    var max = counter.data_.shift();

    if (counter.div_ == undefined)
        counter.div_ = $('#'+counter.div_bar_id_ );

    if (counter.div_txt_ == undefined)
        counter.div_txt_ = $('#'+counter.div_txt_id_ );

    if (max != 0) {
        var value = 100 * d_value / max;
        counter.div_.css("width", value + "%");
        counter.div_txt_.text(value.toFixed(2));// + " " +counter.samples_);

    } else {
        counter.div_txt_.text(d_value.toFixed(0));// + " " +counter.samples_);
        counter.div_.css("width", "0%");
    }
}

GputopUI.prototype.render_bars = function() {
    window.requestAnimationFrame(gputop_ui.window_render_animation_bars);
    // add support for render graphs as well
}

GputopUI.prototype.window_render_animation_bars = function(timestamp) {
    var metric = gputop.query_active_;
    if (metric == undefined)
        return;

    gputop_ui.display_graph(timestamp);

    window.requestAnimationFrame(gputop_ui.window_render_animation_bars);

    for (var i = 0, l = metric.emc_counters_.length; i < l; i++) {
        var counter = metric.emc_counters_[i];
        gputop_ui.display_counter(counter);
    }
}

GputopUI.prototype.metric_not_supported = function(metric) {
    alert(" Metric not supported " + metric.title_)
}

GputopUI.prototype.display_features = function(features) {
    if (features.devinfo.get_devid() == 0 ) {
        gputop_ui.show_alert(" No device was detected, is it the functionality on kernel ? ","alert-danger");
    }

    $( "#gputop-gpu" ).html( gputop.get_arch_pretty_name() );

    $( ".gputop-connecting" ).hide();
    $( "#gputop-cpu" ).html( features.get_cpu_model() );
    $( "#gputop-kernel-build" ).html( features.get_kernel_build() );
    $( "#gputop-kernel-release" ).html( features.get_kernel_release() );
    $( "#gputop-n-cpus" ).html( features.get_n_cpus() );
    $( "#gputop-kernel-performance-query" ).html( features.get_has_gl_performance_query() );
    $( "#gputop-kernel-performance-i915-oa" ).html( features.get_has_i915_oa() );

    $( "#gputop-n-eus" ).html( features.devinfo.get_n_eus().toInt() );
    $( "#gputop-n-eus-slices" ).html( features.devinfo.get_n_eu_slices().toInt()  );
    $( "#gputop-n-eu-threads-count" ).html( features.devinfo.get_eu_threads_count().toInt()  );

    if (features.get_fake_mode())
        $( "#metrics-tab-a" ).html("Metrics (Fake Mode) ");
}

// types of alerts: alert-success alert-info alert-warning alert-danger
GputopUI.prototype.show_alert = function(message,alerttype){

    var dimiss_time = 5000;
    if (alerttype == "alert-success") dimiss_time = 2500; else
    if (alerttype == "alert-info") dimiss_time = 3500; else
    if (alerttype == "alert-danger") dimiss_time = 30000;

    $('#alert_placeholder').append('
×'+message+'
')
        setTimeout(function() { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
            $("#alertdiv").remove();
        }, dimiss_time);
}

GputopUI.prototype.log = function(log_level, log_message){
    var color = "red";
    switch(log_level) {
        case 0: color = "orange"; break;
        case 1: color = "green"; break;
        case 2: color = "yellow"; break;
        case 3: color = "blue"; break;
        case 4: color = "black"; break;
    }
    $('#editor').append(""+log_message+"
");
}

GputopUI.prototype.syslog = function(message){
    log.value += message + "\n";
}

GputopUI.prototype.weblog = function(message){
    //log.value += message + "\n";
}

GputopUI.prototype.init_interface = function(){
    $( "#gputop-overview-panel" ).load( "ajax/overview.html", function() {
        console.log('gputop-overview-panel load');
        gputop.connect();
    });
}

GputopUI.prototype.load_metrics_panel = function(callback_success) {
    $( '#pane2' ).load( "ajax/metrics.html", function() {
        console.log('Metrics panel loaded');
        callback_success();
    });
}

var gputop_ui = new GputopUI();

GputopUI.prototype.btn_close_current_query = function() {
    var active_query = gputop.query_active_;
    if (active_query==undefined) {
        gputop_ui.show_alert(" No Active Query","alert-info");
        return;
    }

    gputop.close_oa_query(active_query.oa_query_id_, function() {
       gputop_ui.show_alert(" Success closing query","alert-info");
    });
}

GputopUI.prototype.update_process = function(process) {

    var pid = process.pid_;
    var name = process.process_name_;

    var tooltip = ''+ pid + ' ' +name+ '';

    $("#sidebar_processes_info").append('
' + tooltip + '
');
    $('#pid_'+pid).click(function (e) {
        console.log("click "+e.target.id);
    });
}

GputopUI.prototype.btn_get_process_info = function() {
    bootbox.prompt("Process Id?", function(result) {
        if (result === null) {
            gputop_ui.show_alert(" Cancelled","alert-info");
        } else {
            var pid = parseInt(result,10);
            if (!isNaN(pid)) {
                gputop.get_process_info(pid, function(msg) {
                    gputop_ui.show_alert(" Callback "+result,"alert-info");
                });
            } else {
                gputop_ui.show_alert("Input not a valid PID","alert-info");
            }
        }
    });
}

// jquery code
$( document ).ready(function() {
    //log = $( "#log" );
    log = document.getElementById("log");

/*
    $( "#gputop-entries" ).append( '
Close Query
' );
    $( '#close_query' ).click( gputop_ui.btn_close_current_query);
*/

    $( '#process-tab-a' ).click(gputop_ui.btn_get_process_info);

    gputop_ui.init_interface();
    $( '#editor' ).wysiwyg();

    // Display tooltips
    $( '[data-toggle="tooltip"]' ).tooltip();

    if (gputop_is_website())
        gputop_load_metric_set('skl');
});
<|endoftext|>


<commit_before>// @flow

const Promise = require("bluebird");
const OpenShiftClient = require('openshift-client');
const sleep = require("es7-sleep");
const AWS = require('aws-sdk');
const uuidv4 = require('uuid/v4');
const { logger } = require('@lagoon/commons/src/local-logging');
const { getOpenShiftInfoForProject } = require('@lagoon/commons/src/api');
const { updateEnvironment } = require('@lagoon/commons/src/api');
const { getEnvironmentByName } = require('@lagoon/commons/src/api');

const { sendToLagoonLogs, initSendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { consumeTaskMonitor, initSendToLagoonTasks } = require('@lagoon/commons/src/tasks');

class BuildNotCompletedYet extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'BuildNotCompletedYet';
  }
}

const accessKeyId =  process.env.AWS_ACCESS_KEY_ID
const secretAccessKey =  process.env.AWS_SECRET_ACCESS_KEY
const bucket = process.env.AWS_BUCKET
const region = process.env.AWS_REGION || 'us-east-2'

if ( !accessKeyId || !secretAccessKey || !bucket) {
  logger.error('AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY or AWS_BUCKET not set.')
}

AWS.config.update({accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, region: region});
const s3 = new AWS.S3();

initSendToLagoonLogs();
initSendToLagoonTasks();

const messageConsumer = async msg => {
  const {
    buildName,
    projectName,
    openshiftProject,
    branchName,
    sha
  } = JSON.parse(msg.content.toString())

  logger.verbose(`Received BuildDeployOpenshift monitoring task for project: ${projectName}, buildName: ${buildName}, openshiftProject: ${openshiftProject}, branch: ${branchName}, sha: ${sha}`);
  let result
  result = await getOpenShiftInfoForProject(projectName);
  const projectOpenshift = result.project

  result = await getEnvironmentByName(`${branchName}`, projectOpenshift.id)
  const environmentOpenshift = result.environmentByName

  try {
    var gitSha = sha
    var openshiftConsole = projectOpenshift.openshift.console_url.replace(/\/$/, "");
    var openshiftToken = projectOpenshift.openshift.token || ""
  } catch(error) {
    logger.warn(`Error while loading information for project ${projectName}: ${error}`)
    throw(error)
  }

  // OpenShift API object
  const openshift = new OpenShiftClient.OApi({
    url: openshiftConsole,
    insecureSkipTlsVerify: true,
    auth: {
      bearer: openshiftToken
    },
  });

  // Kubernetes API Object - needed as some API calls are done to the Kubernetes API part of OpenShift and
  // the OpenShift API does not support them.
  const kubernetes = new OpenShiftClient.Core({
    url: openshiftConsole,
    insecureSkipTlsVerify: true,
    auth: {
      bearer: openshiftToken
    },
  });

  // kubernetes-client does not know about the OpenShift Resources, let's teach it.
  openshift.ns.addResource('builds');

  let projectStatus = {}
  try {
    const projectsGet = Promise.promisify(openshift.projects(openshiftProject).get, { context: openshift.projects(openshiftProject) })
    projectStatus = await projectsGet()
  } catch (err) {
    // a non existing project also throws an error, we check if it's a 404, means it does not exist, so we create it.
    if (err.code == 404) {
      logger.error(`Project ${openshiftProject} does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  try {
    const buildsGet = Promise.promisify(openshift.ns(openshiftProject).builds(buildName).get, { context: openshift.ns(openshiftProject).builds(buildName) })
    buildstatus = await buildsGet()
  } catch (err) {
    if (err.code == 404) {
      logger.error(`Build ${buildName} does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  try {
    const configMapGet = Promise.promisify(kubernetes.ns(openshiftProject).configmaps('lagoon-env').get, { context: kubernetes.ns(openshiftProject).configmaps('lagoon-env') })
    configMap = await configMapGet()
  } catch (err) {
    if (err.code == 404) {
      logger.error(`configmap lagoon-env does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  let logMessage = ''
  if (sha) {
    logMessage = `\`${branchName}\` (${sha.substring(0, 7)})`
  } else {
    logMessage = `\`${branchName}\``
  }

  const buildPhase = buildstatus.status.phase.toLowerCase();
  const buildsLogGet = Promise.promisify(openshift.ns(openshiftProject).builds(`${buildName}/log`).get, { context: openshift.ns(openshiftProject).builds(`${buildName}/log`) })
  const routesGet = Promise.promisify(openshift.ns(openshiftProject).routes.get, { context: openshift.ns(openshiftProject).routes })

  let logLink = ""
  const meta = JSON.parse(msg.content.toString())
  switch (buildPhase) {
    case "new":
    case "pending":
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` not yet started`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` not yet started`)
      break;

    case "running":
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` running`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` running`)
      break;

    case "cancelled":
    case "error":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }
      sendToLagoonLogs('warn', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` cancelled. ${logLink}`
      )
      break;

    case "failed":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }

      sendToLagoonLogs('error', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` failed. ${logLink}`
      )
      break;

    case "complete":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }

      const route = configMap.data.LAGOON_ROUTE
      const routes = configMap.data.LAGOON_ROUTES.split(',').filter(e => e !== route);
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` complete. ${logLink} \n ${route}\n ${routes.join("\n")}`
      )
      try {
        logger.info(configMap.data.LAGOON_ROUTE)
        } catch (err) {
          logger.warn(`${openshiftProject} ${buildName}: Error while updating routes in API, Error: ${err}. Continuing without update`)
        }
      break;

    default:
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` phase ${buildPhase}`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` phase ${buildPhase}`)
      break;
  }

}

const uploadLogToS3 = async (buildName, projectName, branchName, buildLog) => {
  const uuid = uuidv4();
  const path = `${projectName}/${branchName}/${uuid}.txt`

  const params = {
    Bucket: bucket,
    Key:    path,
    Body:   buildLog,
    ACL:    'public-read',
    ContentType: 'text/plain',
  };
  const s3Upload = Promise.promisify(s3.upload, { context: s3 })
  return s3Upload(params);

};

const deathHandler = async (msg, lastError) => {
  const {
    buildName,
    projectName,
    openshiftProject,
    branchName,
    sha
  } = JSON.parse(msg.content.toString())

  let logMessage = ''
  if (sha) {
    logMessage = `\`${branchName}\` (${sha.substring(0, 7)})`
  } else {
    logMessage = `\`${branchName}\``
  }

  sendToLagoonLogs('error', projectName, "", "task:builddeploy-openshift:error",  {},
`*[${projectName}]* ${logMessage} Build \`${buildName}\` ERROR:
\`\`\`
${lastError}
\`\`\``
  )

}

consumeTaskMonitor('builddeploy-openshift', messageConsumer, deathHandler)
<commit_msg>#492 #548 - use better variable names for clarity<commit_after>// @flow

const Promise = require("bluebird");
const OpenShiftClient = require('openshift-client');
const sleep = require("es7-sleep");
const AWS = require('aws-sdk');
const uuidv4 = require('uuid/v4');
const { logger } = require('@lagoon/commons/src/local-logging');
const { getOpenShiftInfoForProject } = require('@lagoon/commons/src/api');
const { updateEnvironment } = require('@lagoon/commons/src/api');
const { getEnvironmentByName } = require('@lagoon/commons/src/api');

const { sendToLagoonLogs, initSendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { consumeTaskMonitor, initSendToLagoonTasks } = require('@lagoon/commons/src/tasks');

class BuildNotCompletedYet extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'BuildNotCompletedYet';
  }
}

const accessKeyId =  process.env.AWS_ACCESS_KEY_ID
const secretAccessKey =  process.env.AWS_SECRET_ACCESS_KEY
const bucket = process.env.AWS_BUCKET
const region = process.env.AWS_REGION || 'us-east-2'

if ( !accessKeyId || !secretAccessKey || !bucket) {
  logger.error('AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY or AWS_BUCKET not set.')
}

AWS.config.update({accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, region: region});
const s3 = new AWS.S3();

initSendToLagoonLogs();
initSendToLagoonTasks();

const messageConsumer = async msg => {
  const {
    buildName,
    projectName,
    openshiftProject,
    branchName,
    sha
  } = JSON.parse(msg.content.toString())

  logger.verbose(`Received BuildDeployOpenshift monitoring task for project: ${projectName}, buildName: ${buildName}, openshiftProject: ${openshiftProject}, branch: ${branchName}, sha: ${sha}`);
  const projectResult = await getOpenShiftInfoForProject(projectName);
  const projectOpenshift = projectResult.project

  const environmentResult = await getEnvironmentByName(`${branchName}`, projectOpenshift.id)
  const environmentOpenshift = environmentResult.environmentByName

  try {
    var gitSha = sha
    var openshiftConsole = projectOpenshift.openshift.console_url.replace(/\/$/, "");
    var openshiftToken = projectOpenshift.openshift.token || ""
  } catch(error) {
    logger.warn(`Error while loading information for project ${projectName}: ${error}`)
    throw(error)
  }

  // OpenShift API object
  const openshift = new OpenShiftClient.OApi({
    url: openshiftConsole,
    insecureSkipTlsVerify: true,
    auth: {
      bearer: openshiftToken
    },
  });

  // Kubernetes API Object - needed as some API calls are done to the Kubernetes API part of OpenShift and
  // the OpenShift API does not support them.
  const kubernetes = new OpenShiftClient.Core({
    url: openshiftConsole,
    insecureSkipTlsVerify: true,
    auth: {
      bearer: openshiftToken
    },
  });

  // kubernetes-client does not know about the OpenShift Resources, let's teach it.
  openshift.ns.addResource('builds');

  let projectStatus = {}
  try {
    const projectsGet = Promise.promisify(openshift.projects(openshiftProject).get, { context: openshift.projects(openshiftProject) })
    projectStatus = await projectsGet()
  } catch (err) {
    // a non existing project also throws an error, we check if it's a 404, means it does not exist, so we create it.
    if (err.code == 404) {
      logger.error(`Project ${openshiftProject} does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  try {
    const buildsGet = Promise.promisify(openshift.ns(openshiftProject).builds(buildName).get, { context: openshift.ns(openshiftProject).builds(buildName) })
    buildstatus = await buildsGet()
  } catch (err) {
    if (err.code == 404) {
      logger.error(`Build ${buildName} does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  try {
    const configMapGet = Promise.promisify(kubernetes.ns(openshiftProject).configmaps('lagoon-env').get, { context: kubernetes.ns(openshiftProject).configmaps('lagoon-env') })
    configMap = await configMapGet()
  } catch (err) {
    if (err.code == 404) {
      logger.error(`configmap lagoon-env does not exist, bailing`)
      return
    } else {
      logger.error(err)
      throw new Error
    }
  }

  let logMessage = ''
  if (sha) {
    logMessage = `\`${branchName}\` (${sha.substring(0, 7)})`
  } else {
    logMessage = `\`${branchName}\``
  }

  const buildPhase = buildstatus.status.phase.toLowerCase();
  const buildsLogGet = Promise.promisify(openshift.ns(openshiftProject).builds(`${buildName}/log`).get, { context: openshift.ns(openshiftProject).builds(`${buildName}/log`) })
  const routesGet = Promise.promisify(openshift.ns(openshiftProject).routes.get, { context: openshift.ns(openshiftProject).routes })

  let logLink = ""
  const meta = JSON.parse(msg.content.toString())
  switch (buildPhase) {
    case "new":
    case "pending":
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` not yet started`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` not yet started`)
      break;

    case "running":
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` running`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` running`)
      break;

    case "cancelled":
    case "error":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }
      sendToLagoonLogs('warn', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` cancelled. ${logLink}`
      )
      break;

    case "failed":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }

      sendToLagoonLogs('error', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` failed. ${logLink}`
      )
      break;

    case "complete":
      try {
        const buildLog = await buildsLogGet()
        const s3UploadResult = await uploadLogToS3(buildName, projectName, branchName, buildLog)
        logLink = `<${s3UploadResult.Location}|Logs>`
      } catch (err) {
        logger.warn(`${openshiftProject} ${buildName}: Error while getting and uploading Logs to S3, Error: ${err}. Continuing without log link in message`)
      }

      const route = configMap.data.LAGOON_ROUTE
      const routes = configMap.data.LAGOON_ROUTES.split(',').filter(e => e !== route);
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` complete. ${logLink} \n ${route}\n ${routes.join("\n")}`
      )
      try {
        logger.info(configMap.data.LAGOON_ROUTE)
        } catch (err) {
          logger.warn(`${openshiftProject} ${buildName}: Error while updating routes in API, Error: ${err}. Continuing without update`)
        }
      break;

    default:
      sendToLagoonLogs('info', projectName, "", `task:builddeploy-openshift:${buildPhase}`, meta,
        `*[${projectName}]* ${logMessage} Build \`${buildName}\` phase ${buildPhase}`
      )
      throw new BuildNotCompletedYet(`*[${projectName}]* ${logMessage} Build \`${buildName}\` phase ${buildPhase}`)
      break;
  }

}

const uploadLogToS3 = async (buildName, projectName, branchName, buildLog) => {
  const uuid = uuidv4();
  const path = `${projectName}/${branchName}/${uuid}.txt`

  const params = {
    Bucket: bucket,
    Key:    path,
    Body:   buildLog,
    ACL:    'public-read',
    ContentType: 'text/plain',
  };
  const s3Upload = Promise.promisify(s3.upload, { context: s3 })
  return s3Upload(params);

};

const deathHandler = async (msg, lastError) => {
  const {
    buildName,
    projectName,
    openshiftProject,
    branchName,
    sha
  } = JSON.parse(msg.content.toString())

  let logMessage = ''
  if (sha) {
    logMessage = `\`${branchName}\` (${sha.substring(0, 7)})`
  } else {
    logMessage = `\`${branchName}\``
  }

  sendToLagoonLogs('error', projectName, "", "task:builddeploy-openshift:error",  {},
`*[${projectName}]* ${logMessage} Build \`${buildName}\` ERROR:
\`\`\`
${lastError}
\`\`\``
  )

}

consumeTaskMonitor('builddeploy-openshift', messageConsumer, deathHandler)
<|endoftext|>


<commit_before>// debug output
let __DEBUG__
function debug (...args) {
  if (__DEBUG__) {
    if (!console.group) {
      args.unshift('%credux-undo', 'font-style: italic')
    }
    console.log(...args)
  }
}
function debugStart (action, state) {
  if (__DEBUG__) {
    const args = ['action', action.type]
    if (console.group) {
      args.unshift('%credux-undo', 'font-style: italic')
      console.groupCollapsed(...args)
      console.log('received', {state, action})
    } else {
      debug(...args)
    }
  }
}
function debugEnd () {
  if (__DEBUG__) {
    return console.groupEnd && console.groupEnd()
  }
}
// /debug output

// action types
export const ActionTypes = {
  UNDO: '@@redux-undo/UNDO',
  REDO: '@@redux-undo/REDO',
  JUMP_TO_FUTURE: '@@redux-undo/JUMP_TO_FUTURE',
  JUMP_TO_PAST: '@@redux-undo/JUMP_TO_PAST',
  CLEAR_HISTORY: '@@redux-undo/CLEAR_HISTORY'
}
// /action types

// action creators to change the state
export const ActionCreators = {
  undo () {
    return { type: ActionTypes.UNDO }
  },
  redo () {
    return { type: ActionTypes.REDO }
  },
  jumpToFuture (index) {
    return { type: ActionTypes.JUMP_TO_FUTURE, index }
  },
  jumpToPast (index) {
    return { type: ActionTypes.JUMP_TO_PAST, index }
  },
  clearHistory () {
    return { type: ActionTypes.CLEAR_HISTORY }
  }
}
// /action creators

// length: get length of history
function length (history) {
  const { past, future } = history
  return past.length + 1 + future.length
}
// /length

// insert: insert `state` into history, which means adding the current state
//         into `past`, setting the new `state` as `present` and erasing
//         the `future`.
function insert (history, state, limit) {
  debug('insert', {state, history, free: limit - length(history)})

  const { past, present } = history
  const historyOverflow = limit && length(history) >= limit

  if (present === undefined) {
    // init history
    return {
      past: [],
      present: state,
      future: []
    }
  }

  return {
    past: [
      ...past.slice(historyOverflow ? 1 : 0),
      present
    ],
    present: state,
    future: []
  }
}
// /insert

// undo: go back to the previous point in history
function undo (history) {
  debug('undo', {history})

  const { past, present, future } = history

  if (past.length <= 0) return history

  return {
    past: past.slice(0, past.length - 1), // remove last element from past
    present: past[past.length - 1], // set element as new present
    future: [
      present, // old present state is in the future now
      ...future
    ]
  }
}
// /undo

// redo: go to the next point in history
function redo (history) {
  debug('redo', {history})

  const { past, present, future } = history

  if (future.length <= 0) return history

  return {
    future: future.slice(1, future.length), // remove element from future
    present: future[0], // set element as new present
    past: [
      ...past,
      present // old present state is in the past now
    ]
  }
}
// /redo

// jumpToFuture: jump to requested index in future history
function jumpToFuture (history, index) {
  if (index === 0) return redo(history)

  const { past, present, future } = history

  return {
    future: future.slice(index + 1),
    present: future[index],
    past: past.concat([present])
              .concat(future.slice(0, index))
  }
}
// /jumpToFuture

// jumpToPast: jump to requested index in past history
function jumpToPast (history, index) {
  if (index === history.past.length - 1) return undo(history)

  const { past, present, future } = history

  return {
    future: past.slice(index + 1)
                .concat([present])
                .concat(future),
    present: past[index],
    past: past.slice(0, index)
  }
}
// /jumpToPast

// createHistory
function createHistory (state) {
  return {
    past: [],
    present: state,
    future: []
  }
}
// /createHistory

// parseActions
export function parseActions (rawActions, defaultValue = []) {
  if (Array.isArray(rawActions)) {
    return rawActions
  } else if (typeof rawActions === 'string') {
    return [rawActions]
  }
  return defaultValue
}
// /parseActions

// redux-undo higher order reducer
export default function undoable (reducer, rawConfig = {}) {
  __DEBUG__ = rawConfig.debug

  const config = {
    initialState: rawConfig.initialState,
    initTypes: parseActions(rawConfig.initTypes, ['@@redux/INIT', '@@INIT']),
    limit: rawConfig.limit,
    filter: rawConfig.filter || (() => true),
    undoType: rawConfig.undoType || ActionTypes.UNDO,
    redoType: rawConfig.redoType || ActionTypes.REDO,
    jumpToPastType: rawConfig.jumpToPastType || ActionTypes.JUMP_TO_PAST,
    jumpToFutureType: rawConfig.jumpToFutureType || ActionTypes.JUMP_TO_FUTURE,
    clearHistoryType: rawConfig.clearHistoryType || ActionTypes.CLEAR_HISTORY
  }
  config.history = rawConfig.initialHistory || createHistory(config.initialState)

  if (config.initTypes.length === 0) {
    console.warn('redux-undo: supply at least one action type in initTypes to ensure initial state')
  }

  return (state, action) => {
    debugStart(action, state)
    let res
    switch (action.type) {
      case config.undoType:
        res = undo(state)
        debug('after undo', res)
        debugEnd()
        return res

      case config.redoType:
        res = redo(state)
        debug('after redo', res)
        debugEnd()
        return res

      case config.jumpToPastType:
        res = jumpToPast(state, action.index)
        debug('after jumpToPast', res)
        debugEnd()
        return res

      case config.jumpToFutureType:
        res = jumpToFuture(state, action.index)
        debug('after jumpToFuture', res)
        debugEnd()
        return res

      case config.clearHistoryType:
        res = createHistory(state.present)
        debug('cleared history', res)
        debugEnd()
        return res

      default:
        res = reducer(state && state.present, action)

        if (config.initTypes.some((actionType) => actionType === action.type)) {
          debug('reset history due to init action')
          debugEnd()
          return createHistory(res)
        }

        if (config.filter && typeof config.filter === 'function') {
          if (!config.filter(action, res, state && state.present)) {
            debug('filter prevented action, not storing it')
            debugEnd()
            return {
              ...state,
              present: res
            }
          }
        }

        const history = (state && state.present !== undefined) ? state : config.history
        const updatedHistory = insert(history, res, config.limit)
        debug('after insert', {history: updatedHistory, free: config.limit - length(updatedHistory)})
        debugEnd()
        return updatedHistory
    }
  }
}
// /redux-undo

// distinctState helper
export function distinctState () {
  return (action, currentState, previousState) => currentState !== previousState
}
// /distinctState

// includeAction helper
export function includeAction (rawActions) {
  const actions = parseActions(rawActions)
  return (action) => actions.indexOf(action.type) >= 0
}
// /includeAction

// excludeAction helper
export function excludeAction (rawActions = []) {
  const actions = parseActions(rawActions)
  return (action) => actions.indexOf(action.type) < 0
}
// /excludeAction
<commit_msg>1. For `jumpToPast` and `jumpToFuture`, if the `index` is out of bounds, the action should do nothing.<commit_after>// debug output
let __DEBUG__
function debug (...args) {
  if (__DEBUG__) {
    if (!console.group) {
      args.unshift('%credux-undo', 'font-style: italic')
    }
    console.log(...args)
  }
}
function debugStart (action, state) {
  if (__DEBUG__) {
    const args = ['action', action.type]
    if (console.group) {
      args.unshift('%credux-undo', 'font-style: italic')
      console.groupCollapsed(...args)
      console.log('received', {state, action})
    } else {
      debug(...args)
    }
  }
}
function debugEnd () {
  if (__DEBUG__) {
    return console.groupEnd && console.groupEnd()
  }
}
// /debug output

// action types
export const ActionTypes = {
  UNDO: '@@redux-undo/UNDO',
  REDO: '@@redux-undo/REDO',
  JUMP_TO_FUTURE: '@@redux-undo/JUMP_TO_FUTURE',
  JUMP_TO_PAST: '@@redux-undo/JUMP_TO_PAST',
  CLEAR_HISTORY: '@@redux-undo/CLEAR_HISTORY'
}
// /action types

// action creators to change the state
export const ActionCreators = {
  undo () {
    return { type: ActionTypes.UNDO }
  },
  redo () {
    return { type: ActionTypes.REDO }
  },
  jumpToFuture (index) {
    return { type: ActionTypes.JUMP_TO_FUTURE, index }
  },
  jumpToPast (index) {
    return { type: ActionTypes.JUMP_TO_PAST, index }
  },
  clearHistory () {
    return { type: ActionTypes.CLEAR_HISTORY }
  }
}
// /action creators

// length: get length of history
function length (history) {
  const { past, future } = history
  return past.length + 1 + future.length
}
// /length

// insert: insert `state` into history, which means adding the current state
//         into `past`, setting the new `state` as `present` and erasing
//         the `future`.
function insert (history, state, limit) {
  debug('insert', {state, history, free: limit - length(history)})

  const { past, present } = history
  const historyOverflow = limit && length(history) >= limit

  if (present === undefined) {
    // init history
    return {
      past: [],
      present: state,
      future: []
    }
  }

  return {
    past: [
      ...past.slice(historyOverflow ? 1 : 0),
      present
    ],
    present: state,
    future: []
  }
}
// /insert

// undo: go back to the previous point in history
function undo (history) {
  debug('undo', {history})

  const { past, present, future } = history

  if (past.length <= 0) return history

  return {
    past: past.slice(0, past.length - 1), // remove last element from past
    present: past[past.length - 1], // set element as new present
    future: [
      present, // old present state is in the future now
      ...future
    ]
  }
}
// /undo

// redo: go to the next point in history
function redo (history) {
  debug('redo', {history})

  const { past, present, future } = history

  if (future.length <= 0) return history

  return {
    future: future.slice(1, future.length), // remove element from future
    present: future[0], // set element as new present
    past: [
      ...past,
      present // old present state is in the past now
    ]
  }
}
// /redo

// jumpToFuture: jump to requested index in future history
function jumpToFuture (history, index) {
  if (index === 0) return redo(history)
  if (index < 0 || index >= history.future.length) return history

  const { past, present, future } = history

  return {
    future: future.slice(index + 1),
    present: future[index],
    past: past.concat([present])
              .concat(future.slice(0, index))
  }
}
// /jumpToFuture

// jumpToPast: jump to requested index in past history
function jumpToPast (history, index) {
  if (index === history.past.length - 1) return undo(history)
  if (index < 0 || index >= history.past.length) return history

  const { past, present, future } = history

  return {
    future: past.slice(index + 1)
                .concat([present])
                .concat(future),
    present: past[index],
    past: past.slice(0, index)
  }
}
// /jumpToPast

// createHistory
function createHistory (state) {
  return {
    past: [],
    present: state,
    future: []
  }
}
// /createHistory

// parseActions
export function parseActions (rawActions, defaultValue = []) {
  if (Array.isArray(rawActions)) {
    return rawActions
  } else if (typeof rawActions === 'string') {
    return [rawActions]
  }
  return defaultValue
}
// /parseActions

// redux-undo higher order reducer
export default function undoable (reducer, rawConfig = {}) {
  __DEBUG__ = rawConfig.debug

  const config = {
    initialState: rawConfig.initialState,
    initTypes: parseActions(rawConfig.initTypes, ['@@redux/INIT', '@@INIT']),
    limit: rawConfig.limit,
    filter: rawConfig.filter || (() => true),
    undoType: rawConfig.undoType || ActionTypes.UNDO,
    redoType: rawConfig.redoType || ActionTypes.REDO,
    jumpToPastType: rawConfig.jumpToPastType || ActionTypes.JUMP_TO_PAST,
    jumpToFutureType: rawConfig.jumpToFutureType || ActionTypes.JUMP_TO_FUTURE,
    clearHistoryType: rawConfig.clearHistoryType || ActionTypes.CLEAR_HISTORY
  }
  config.history = rawConfig.initialHistory || createHistory(config.initialState || reducer(undefined, {}))

  if (config.initTypes.length === 0) {
    console.warn('redux-undo: supply at least one action type in initTypes to ensure initial state')
  }

  return (state = config.history, action = {}) => {
    debugStart(action, state)
    let res
    switch (action.type) {
      case undefined:
        return state

      case config.undoType:
        res = undo(state)
        debug('after undo', res)
        debugEnd()
        return res

      case config.redoType:
        res = redo(state)
        debug('after redo', res)
        debugEnd()
        return res

      case config.jumpToPastType:
        res = jumpToPast(state, action.index)
        debug('after jumpToPast', res)
        debugEnd()
        return res

      case config.jumpToFutureType:
        res = jumpToFuture(state, action.index)
        debug('after jumpToFuture', res)
        debugEnd()
        return res

      case config.clearHistoryType:
        res = createHistory(state.present)
        debug('cleared history', res)
        debugEnd()
        return res

      default:
        res = reducer(state && state.present, action)

        if (config.initTypes.some((actionType) => actionType === action.type)) {
          debug('reset history due to init action')
          debugEnd()
          return config.history
        }

        if (config.filter && typeof config.filter === 'function') {
          if (!config.filter(action, res, state && state.present)) {
            debug('filter prevented action, not storing it')
            debugEnd()
            return {
              ...state,
              present: res
            }
          }
        }

        const updatedHistory = insert(state, res, config.limit)
        debug('after insert', {history: updatedHistory, free: config.limit - length(updatedHistory)})
        debugEnd()
        return updatedHistory
    }
  }
}
// /redux-undo

// distinctState helper
export function distinctState () {
  return (action, currentState, previousState) => currentState !== previousState
}
// /distinctState

// includeAction helper
export function includeAction (rawActions) {
  const actions = parseActions(rawActions)
  return (action) => actions.indexOf(action.type) >= 0
}
// /includeAction

// excludeAction helper
export function excludeAction (rawActions = []) {
  const actions = parseActions(rawActions)
  return (action) => actions.indexOf(action.type) < 0
}
// /excludeAction
<|endoftext|>


<commit_before>'use strict';

(function() {
  angular.module('ncsaas')
    .controller('AuthController', ['$state', 'authService', 'baseControllerClass', 'ncUtilsFlash', '$rootScope', AuthController]);

  function AuthController($state, authService, baseControllerClass, ncUtilsFlash, $rootScope) {
    var controllerScope = this;
    var Controller = baseControllerClass.extend({
      isSignupFormVisible: false,
      user: {},
      errors: {},

      init: function() {
        this._super();
      },
      signin: function() {
        var vm = this;
        $rootScope.$broadcast('enableRequests');
        return authService.signin(vm.user.username, vm.user.password).then(vm.loginSuccess.bind(vm), vm.loginError.bind(vm));
      },
      authenticate: function(provider) {
        var vm = this;
        $rootScope.$broadcast('enableRequests');
        authService.authenticate(provider).then(vm.loginSuccess.bind(vm), vm.loginError.bind(vm));
      },
      loginSuccess: function() {
        $state.go('dashboard.index');
        return true;
      },
      loginError: function(response) {
        this.errors = [];
        if (response.status != 400 && +response.status > 0) {
          this.errors[response.status] = response.statusText + ' Authentication failed';
        } else {
          this.errors = response.data;
        }
      },
      getErrors: function() {
        var vm = this;
        if (vm.errors !== undefined) {
          var prettyErrors = [];
          if (Object.prototype.toString.call(vm.errors) === '[object String]') {
            prettyErrors.push(vm.errors);
            return prettyErrors;
          }
          for (var key in vm.errors) {
            if (vm.errors.hasOwnProperty(key)) {
              if (Object.prototype.toString.call(vm.errors[key]) === '[object Array]') {
                prettyErrors.push(key + ': ' + vm.errors[key].join(', '));
              } else {
                prettyErrors.push(key + ': ' + vm.errors[key]);
              }
            }
          }
          return prettyErrors;
        } else {
          return '';
        }
      },
      signup: function() {
        var vm = this;
        vm.errors = {};
        $rootScope.$broadcast('enableRequests');
        return authService.signup(vm.user).then(function() {
          ncUtilsFlash.info('Confirmation mail has been sent. Please check your inbox!');
          vm.isSignupFormVisible = false;
          vm.user = {};
          return true;
        }, function(response) {
          vm.errors = response.data;
        });
      }
    });

    controllerScope.__proto__ = new Controller();
  }

})();

(function() {
  angular.module('ncsaas')
    .controller('ActivationController', [
      '$location', '$stateParams', 'authService', 'baseControllerClass', 'ncUtilsFlash', ActivationController]);

  function ActivationController($location, $stateParams, authService, baseControllerClass, ncUtilsFlash) {
    var controllerScope = this;
    var Controller = baseControllerClass.extend({
      init: function() {
        this._super();
        authService.activate({
          user_uuid: $stateParams.user_uuid,
          token: $stateParams.token
        }).then(function() {
          ncUtilsFlash.info('Account has been activated');
          $location.path('/initial-data/');
        }, function(response) {
          ncUtilsFlash.error('Unable to activate account');
        });
      }
    });

    controllerScope.__proto__ = new Controller();
  }
})();
<commit_msg>Added TODO comment (SAAS-1078)<commit_after>'use strict';

(function() {
  angular.module('ncsaas')
    .controller('AuthController', ['$state', 'authService', 'baseControllerClass', 'ncUtilsFlash', '$rootScope', AuthController]);

  function AuthController($state, authService, baseControllerClass, ncUtilsFlash, $rootScope) {
    var controllerScope = this;
    var Controller = baseControllerClass.extend({
      isSignupFormVisible: false,
      user: {},
      errors: {},

      init: function() {
        this._super();
      },
      signin: function() {
        var vm = this;
        $rootScope.$broadcast('enableRequests');
        return authService.signin(vm.user.username, vm.user.password).then(vm.loginSuccess.bind(vm), vm.loginError.bind(vm));
      },
      authenticate: function(provider) {
        var vm = this;
        $rootScope.$broadcast('enableRequests');
        authService.authenticate(provider).then(vm.loginSuccess.bind(vm), vm.loginError.bind(vm));
      },
      loginSuccess: function() {
        $state.go('dashboard.index');
        return true;
      },
      loginError: function(response) {
        this.errors = [];
        if (response.status != 400 && +response.status > 0) {
          this.errors[response.status] = response.statusText + ' Authentication failed';
        } else {
          this.errors = response.data;
        }
      },
      getErrors: function() {
        var vm = this;
        if (vm.errors !== undefined) {
          var prettyErrors = [];
          if (Object.prototype.toString.call(vm.errors) === '[object String]') {
            prettyErrors.push(vm.errors);
            return prettyErrors;
          }
          for (var key in vm.errors) {
            if (vm.errors.hasOwnProperty(key)) {
              if (Object.prototype.toString.call(vm.errors[key]) === '[object Array]') {
                prettyErrors.push(key + ': ' + vm.errors[key].join(', '));
              } else {
                prettyErrors.push(key + ': ' + vm.errors[key]);
              }
            }
          }
          return prettyErrors;
        } else {
          return '';
        }
      },
      signup: function() {
        var vm = this;
        vm.errors = {};
        $rootScope.$broadcast('enableRequests');
        return authService.signup(vm.user).then(function() {
          ncUtilsFlash.info('Confirmation mail has been sent. Please check your inbox!');
          vm.isSignupFormVisible = false;
          vm.user = {};
          return true;
        }, function(response) {
          vm.errors = response.data;
        });
      }
    });

    controllerScope.__proto__ = new Controller();
  }

})();

(function() {
  angular.module('ncsaas')
    .controller('ActivationController', [
      '$location', '$stateParams', 'authService', 'baseControllerClass', 'ncUtilsFlash', ActivationController]);

  function ActivationController($location, $stateParams, authService, baseControllerClass, ncUtilsFlash) {
    var controllerScope = this;
    var Controller = baseControllerClass.extend({
      init: function() {
        this._super();
        authService.activate({
          user_uuid: $stateParams.user_uuid,
          token: $stateParams.token
        }).then(function() {
          ncUtilsFlash.info('Account has been activated');
          // TODO: find the way to avoid hardcode for the path
          $location.path('/initial-data/');
        }, function(response) {
          ncUtilsFlash.error('Unable to activate account');
        });
      }
    });

    controllerScope.__proto__ = new Controller();
  }
})();
<|endoftext|>


<commit_before>export default class HttpUtils {
	static get(url) {
		return new Promise((resolve,reject)=> {
			fetch(url)
				.then(response=>response.json())
				.then(result=>{
					resolve(result);
				})
				.catch(error=>{
					reject(error);
				});
		});
	}
	static post(url, data) {
		return new Promise((resolve, reject) => {
			// alert(JSON.stringify(data))
			fetch(url, {
				method: "POST",
				headers:{
					"Accept": "application/json",
					"Content-Type": "application/x-www-form-urlencoded"
				},
				body: this.changeData(data)
			})
			    .then(response=>response.json())
			    .then(result=>{
			    	resolve(result);
			    })
			    .catch(error=>{
					reject(error);
				});
		});
	}
	static changeData(obj) {
		var prop,str="";
		var i = 0;
		for(prop in obj) {
			if(!prop) {
				return ;
			}
			if(i==0) {
				str += prop+'='+obj[prop];
			} else {
				str+="&" + prop+'='+obj[prop];
			}
			i++;
		}
		// alert(str);
		return str
	}
}<commit_msg>refactor httputils<commit_after>export default class HttpUtils {
  static get(url) {
    return new Promise((resolve, reject) => {
      fetch(url)
        .then(response => response.json())
        .then(result => {
          resolve(result)
        })
        .catch(error => {
          reject(error)
        })
    })
  }
  static post(url, data) {
    return new Promise((resolve, reject) => {
      // alert(JSON.stringify(data))
      fetch(url, {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/x-www-form-urlencoded"
        },
        body: this.changeData(data)
      })
        .then(response => response.json())
        .then(result => {
          resolve(result)
        })
        .catch(error => {
          reject(error)
        })
    })
  }
  static changeData(obj) {
    var prop,
      str = ""
    var i = 0
    for (prop in obj) {
      if (!prop) {
        return
      }
      if (i == 0) {
        str += prop + "=" + obj[prop]
      } else {
        str += "&" + prop + "=" + obj[prop]
      }
      i++
    }
    // alert(str);
    return str
  }
}
<|endoftext|>