<commit_before>var SUPPORTED_IMAGE_TYPES = ['jpg','jpeg','png','gif'];

var Semver = function(ver) {
  var segs = ver.split('.');
  return { major: (segs[0] || 0), minor: (segs[1] || 0), patch: (segs[2] || 0), version: ver };
};

var isValidFileType = function(extension) {
  return SUPPORTED_IMAGE_TYPES.indexOf(extension) >= 0;
};

var createAssetInput = function() {
  var assetInput = document.createElement('input');

  assetInput.type = 'file';
  assetInput.style.display = 'none';
  assetInput.id = 'asset-input';

  // Stop event propagation to make sure we don't set editable state to false
  //  - when we click on the input[type="file"]
  assetInput.onclick = function(event) {
    event.stopPropagation();
  };

  return assetInput;
};

var createAssetDropzone = function() {
  var assetDropzone = document.createElement('div');
  var innerHTML = '

Drop file here or click to upload
';
  innerHTML += '
cancel

';

  assetDropzone.innerHTML = innerHTML;
  assetDropzone.className = 'asset-dropzone hidden';

  return assetDropzone;
};

var onDragOverDropzone = function(evt) {
  evt.stopPropagation();
  evt.preventDefault();
  evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
};

var createLoadingOverlay = function() {
  var loadingOverlay = document.createElement('div');
  loadingOverlay.className = 'asset-loading-overlay hidden';
  loadingOverlay.innerHTML = '
Uploading asset...
';

  return loadingOverlay;
};

var postAsset = function(url, sessionId, assetData, callback) {
  var request = new XMLHttpRequest();

  var formData = new FormData();
  Object.keys(assetData).forEach(function(key) {
    if (key === 'tags') {
      formData.append(key, JSON.stringify(assetData[key]));
    } else {
      formData.append(key, assetData[key]);
    }
  });

  request.onload = function() {
    if (request.readyState == 4) {
      if (request.status == 201) {
        return callback(null, JSON.parse(request.responseText));
      } else {
        return callback(new Error('Something went wrong when uploading an asset. please try again'));
      }
    }
  };

  request.open('POST', url + '/assets', true);
  request.setRequestHeader('SID', sessionId);
  request.send(formData);
};

var serializeFile = function(file) {
  var fileNameSplit = file.name.split('.'),
      extension     = fileNameSplit[fileNameSplit.length - 1],
      contentType   = file.type || 'image/x-' + extension;

  if (!isValidFileType(extension)) {
    return console.warn('invalid file type:', extension);
  }

  var attributes = {
    title:        'New File',
    type:         'image',
    tags:         ['image'],
    content:      file,
    contentType:  contentType
  };

  return attributes;
};

var patch = function(to, from) {
  if(from) {
    Object.keys(from).forEach(function(key){
      to[key] = from[key];
      if (to[key] === null) {
        delete to[key];
      }
    });
  }
  return to;
};

var isNullish = function(obj) {
  return obj == null; // jshint ignore:line
};

var JSONDeepEquals = function(o1, o2) {
  if (typeof o1 !== "object" || typeof o1 !== typeof o2 || isNullish(o1) || isNullish(o2)) {
    return o1 === o2;
  }

  var k1 = Object.keys(o1).sort();
  var k2 = Object.keys(o2).sort();
  if (k1.length != k2.length) return false;

  for (var i=0; i<k1.length; i++) {
    if (!JSONDeepEquals(o1[k1[i]], o2[k2[i]])) return false;
  }
  return true;
};

var prototype = Object.create(HTMLElement.prototype, {
  src: {
    get: function(){ return this.getAttribute('src') || 'about:blank'; }
  },

  editable: {
    get: function(){ return this.getAttribute('editable') == 'true'; }
  },

  env: {
    get: function(){ return this.readAttributeAsJson('data-environment'); }
  },

  config: {
    get: function(){ return this.readAttributeAsJson('data-config'); }
  },

  userstate: {
    get: function(){ return this.readAttributeAsJson('data-userstate'); }
  },

  debug: {
    get: function(){ return this.hasAttribute('debug'); }
  },

  apiVersion: {
    get: function(){
      if(!this._apiVersion) {
        this._apiVersion = new Semver(this.getAttribute('data-api-version') || '0.0.0');
      }
      return this._apiVersion;
    }
  }
});

prototype.readAttributeAsJson = function(name) {
  if(!this.hasAttribute(name)) { return {}; }
  return JSON.parse(this.getAttribute(name));
};

prototype.log = function(dir, event, data) {
  if(this.debug) { console.log(dir, event, data); }
};

prototype.createdCallback = function() {
  this._previousMessages = {};
};

prototype.attachedCallback = function(){
  this.iframe = document.createElement('iframe');
  this.iframe.src = this.src;
  this.iframe.addEventListener('message', this.handleMessage.bind(this));
  this.iframe.setAttribute('allowfullscreen', 'allowfullscreen');

  this.appendChild(this.iframe);

  this.assetInput     = createAssetInput();
  this.loadingOverlay = createLoadingOverlay();
  this.assetDropzone  = createAssetDropzone();

  this.appendChild(this.assetInput);
  this.appendChild(this.assetDropzone);
  this.appendChild(this.loadingOverlay);
};

prototype.detachedCallback = function(){
  this.removeChild(this.iframe);
  this.removeChild(this.assetInput);
  this.removeChild(this.assetDropzone);
  this.removeChild(this.loadingOverlay);
  this._reset();
};

prototype._reset = function(){
  this._previousMessages = {};
  window.clearTimeout(this._attributesChangedTimeout);
  window.clearTimeout(this._learnerStateChangedTimeout);
};

prototype.attributeChangedCallback = function(name, oldAttribute, newAttribute){
  switch(name) {
    case 'editable':
      this.sendMessage('editableChanged', { editable: this.editable });
      if(this.apiVersion.minor < 1) {
        this.sendMessage('setEditable', { editable: this.editable });
      }
      if (this.assetDropzone) { this.hideAssetDropzone(); }
      break;

    case 'data-config':
      window.clearTimeout(this._attributesChangedTimeout);
      this._attributesChangedTimeout = window.setTimeout((function() {
        this.sendMessage('attributesChanged', this.config);
      }).bind(this));
      break;

    case 'data-userstate':
      window.clearTimeout(this._learnerStateChangedTimeout);
      this._learnerStateChangedTimeout = window.setTimeout((function() {
        this.sendMessage('learnerStateChanged', this.userstate);
      }).bind(this));
      break;
  }
};

prototype.handleMessage = function(event) {
  if(event.detail.event) {
    var eventName = event.detail.event;
    var data = event.detail.data;

    this.log('↖', eventName, data);

    var handler = this.messageHandlers[eventName];
    if(handler) {
      handler.call(this, data);
    } else {
      console.error('Unknown event received: ' + eventName);
      this.error({message: 'Unknown event received: ' + eventName});
    }
  }
};

prototype.sendMessage = function(eventName, data) {
  if (!this._listening) return;
  if (JSONDeepEquals(this._previousMessages[eventName], data)) return;

  var message = { event: eventName };
  if(data) { message.data = data; }
  if(this.iframe && this.iframe.contentWindow) {
    this.iframe.contentWindow.postMessage(message, '*');
    this.log('↘', message.event, message.data);
    this._previousMessages[eventName] = data;
  }
};

prototype.fireCustomEvent = function(eventName, data, options) {
  options = options || {};
  var evt = new CustomEvent(eventName, { detail: data, bubbles: options.bubbles || false });
  this.dispatchEvent(evt);
};

prototype.hideAssetDropzone = function() {
  this.assetDropzone.className = 'asset-dropzone hidden';
  this.assetDropzone.removeEventListener('drop', this.onDropAssetDropzone);
  this.assetDropzone.removeEventListener('dragover', onDragOverDropzone);
};

prototype.onDropAssetDropzone = function(data, event) {
  event.stopPropagation();
  event.preventDefault();
  var dataTransfer = event.dataTransfer;

  if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
    this.uploadAssetAndSetAttributes(data, dataTransfer.files[0]);
  }
};

prototype.setupDropzoneHandlers = function(requestData) {
  this.assetDropzone.onclick = function() {
    this.assetInput.click();
  }.bind(this);

  this.querySelector('.dropzone-cancel-dialog').onclick = function(event) {
    event.preventDefault();
    event.stopPropagation();
    this.hideAssetDropzone();
  }.bind(this);

  this.assetDropzone.addEventListener('dragover', onDragOverDropzone, false);
  this.assetDropzone.addEventListener('drop', this.onDropAssetDropzone.bind(this, requestData), false);
};

prototype.uploadAssetAndSetAttributes = function(data, file) {
  var apiUrl      = this.env.apiUrl,
      sessionId   = this.env.sessionId,
      serializedFile = serializeFile(file);

  if (!serializedFile) { return; }

  // To patch attributesChanged if author toggles out of gadget editing
  this.uploadingAsset = true;

  this.assetDropzone.className  = 'asset-dropzone hidden';
  this.loadingOverlay.className = 'asset-loading-overlay';

  postAsset(apiUrl, sessionId, serializedFile, function(error, assetJson) {
    this.loadingOverlay.className = 'asset-loading-overlay hidden';
    if (error) {
      return alert(error.message);
    }

    assetAttributes = {};
    assetAttributes[data.attribute] = assetJson;

    this.sendMessage('attributesChanged', assetAttributes);
    // After a period of time allotted to communicate the change to 'attributesChanged'
    // set uploadingAsset to false
    setTimeout(function() { this.uploadingAsset = false; }.bind(this), 1000);
  }.bind(this));
};

prototype.messageHandlers = {
  startListening: function(){
    this._reset();
    this._listening = true;
    this.sendMessage('environmentChanged', this.env);
    this.sendMessage('attributesChanged', this.config);
    this.sendMessage('learnerStateChanged', this.userstate);
    this.sendMessage('editableChanged', { editable: this.editable });
  },

  setHeight: function(data){
    this.iframe.style.height = data.pixels + 'px';
    if (!this._firedRendered) {
      this._firedRendered = true;
      this.fireCustomEvent('rendered');
    }
  },

  setAttributes: function(data){
    if(!this.editable && !this.uploadingAsset) {
      console.warn('Unable to setAttributes in the read-only state');
      return;
    }
    var config = this.readAttributeAsJson('data-config');
    patch(config, data);
    this.setAttribute('data-config', JSON.stringify(config));

    // Player needs those events, until we have mutation observers in place
    this.fireCustomEvent('setAttributes', config);
  },

  setLearnerState: function(data) {
    var userstate = this.readAttributeAsJson('data-userstate');
    patch(userstate, data);
    this.setAttribute('data-userstate', JSON.stringify(userstate));

    // Player needs those events, until we have mutation observers in place
    this.fireCustomEvent('setLearnerState', userstate);
  },

  getPath: function(data) {
    console.warn('getPath/setPath are obsolete');
    var assetUrlTemplate = this.env && this.env.assetUrlTemplate;
    if(assetUrlTemplate) {
      var url = assetUrlTemplate.replace('<%= id %>', data.assetId );
      this.sendMessage('setPath', { url: url});
    }
  },

  setPropertySheetAttributes: function(data) { this.fireCustomEvent('setPropertySheetAttributes', data); },
  track: function(data) { this.fireCustomEvent('track', data, {bubbles: true}); },
  error: function(data) { this.fireCustomEvent('error', data, {bubbles: true}); },
  requestAsset: function(data) {
    // TODO support other updload types
    if (data.type == 'video') {
      return this.fireCustomEvent('requestAsset', data);
    }

    this.assetDropzone.className = 'asset-dropzone';
    this.setupDropzoneHandlers(data);

    this.assetInput.onchange = function(e) {
      if (e && e.target && e.target.files && e.target.files[0]) {
        this.uploadAssetAndSetAttributes(data, e.target.files[0]);
      }
    }.bind(this);
  },

  // Soon to be deprecated in favour of in-iframe APIs
  // E.g. https://github.com/Versal/challenges-js-api/
  setEmpty: function(data) { this.fireCustomEvent('setEmpty', data); },
  changeBlocking: function(data) { this.fireCustomEvent('changeBlocking', data); }
};

window.addEventListener('message', function(event){
  var iframes = document.querySelectorAll('versal-iframe-launcher > iframe');
  Array.prototype.forEach.call(iframes, function(iframe){
    if(iframe.contentWindow == event.source) {
      iframe.dispatchEvent(new CustomEvent('message', { detail: event.data }));
    }
  });
});

document.registerElement('versal-iframe-launcher', { prototype: prototype });
<commit_msg>avoid creating and initializing the content iframe if one already exists<commit_after>var SUPPORTED_IMAGE_TYPES = ['jpg','jpeg','png','gif'];

var Semver = function(ver) {
  var segs = ver.split('.');
  return { major: (segs[0] || 0), minor: (segs[1] || 0), patch: (segs[2] || 0), version: ver };
};

var isValidFileType = function(extension) {
  return SUPPORTED_IMAGE_TYPES.indexOf(extension) >= 0;
};

var createAssetInput = function() {
  var assetInput = document.createElement('input');

  assetInput.type = 'file';
  assetInput.style.display = 'none';
  assetInput.id = 'asset-input';

  // Stop event propagation to make sure we don't set editable state to false
  //  - when we click on the input[type="file"]
  assetInput.onclick = function(event) {
    event.stopPropagation();
  };

  return assetInput;
};

var createAssetDropzone = function() {
  var assetDropzone = document.createElement('div');
  var innerHTML = '

Drop file here or click to upload
';
  innerHTML += '
cancel

';

  assetDropzone.innerHTML = innerHTML;
  assetDropzone.className = 'asset-dropzone hidden';

  return assetDropzone;
};

var onDragOverDropzone = function(evt) {
  evt.stopPropagation();
  evt.preventDefault();
  evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
};

var createLoadingOverlay = function() {
  var loadingOverlay = document.createElement('div');
  loadingOverlay.className = 'asset-loading-overlay hidden';
  loadingOverlay.innerHTML = '
Uploading asset...
';

  return loadingOverlay;
};

var postAsset = function(url, sessionId, assetData, callback) {
  var request = new XMLHttpRequest();

  var formData = new FormData();
  Object.keys(assetData).forEach(function(key) {
    if (key === 'tags') {
      formData.append(key, JSON.stringify(assetData[key]));
    } else {
      formData.append(key, assetData[key]);
    }
  });

  request.onload = function() {
    if (request.readyState == 4) {
      if (request.status == 201) {
        return callback(null, JSON.parse(request.responseText));
      } else {
        return callback(new Error('Something went wrong when uploading an asset. please try again'));
      }
    }
  };

  request.open('POST', url + '/assets', true);
  request.setRequestHeader('SID', sessionId);
  request.send(formData);
};

var serializeFile = function(file) {
  var fileNameSplit = file.name.split('.'),
      extension     = fileNameSplit[fileNameSplit.length - 1],
      contentType   = file.type || 'image/x-' + extension;

  if (!isValidFileType(extension)) {
    return console.warn('invalid file type:', extension);
  }

  var attributes = {
    title:        'New File',
    type:         'image',
    tags:         ['image'],
    content:      file,
    contentType:  contentType
  };

  return attributes;
};

var patch = function(to, from) {
  if(from) {
    Object.keys(from).forEach(function(key){
      to[key] = from[key];
      if (to[key] === null) {
        delete to[key];
      }
    });
  }
  return to;
};

var isNullish = function(obj) {
  return obj == null; // jshint ignore:line
};

var JSONDeepEquals = function(o1, o2) {
  if (typeof o1 !== "object" || typeof o1 !== typeof o2 || isNullish(o1) || isNullish(o2)) {
    return o1 === o2;
  }

  var k1 = Object.keys(o1).sort();
  var k2 = Object.keys(o2).sort();
  if (k1.length != k2.length) return false;

  for (var i=0; i<k1.length; i++) {
    if (!JSONDeepEquals(o1[k1[i]], o2[k2[i]])) return false;
  }
  return true;
};

var prototype = Object.create(HTMLElement.prototype, {
  src: {
    get: function(){ return this.getAttribute('src') || 'about:blank'; }
  },

  editable: {
    get: function(){ return this.getAttribute('editable') == 'true'; }
  },

  env: {
    get: function(){ return this.readAttributeAsJson('data-environment'); }
  },

  config: {
    get: function(){ return this.readAttributeAsJson('data-config'); }
  },

  userstate: {
    get: function(){ return this.readAttributeAsJson('data-userstate'); }
  },

  debug: {
    get: function(){ return this.hasAttribute('debug'); }
  },

  apiVersion: {
    get: function(){
      if(!this._apiVersion) {
        this._apiVersion = new Semver(this.getAttribute('data-api-version') || '0.0.0');
      }
      return this._apiVersion;
    }
  }
});

prototype.readAttributeAsJson = function(name) {
  if(!this.hasAttribute(name)) { return {}; }
  return JSON.parse(this.getAttribute(name));
};

prototype.log = function(dir, event, data) {
  if(this.debug) { console.log(dir, event, data); }
};

prototype.createdCallback = function() {
  this._previousMessages = {};
};

prototype.attachedCallback = function(){
  // avoid problems in case attachedCallback is called multiple times while detachedCallback is not called
  if (this.iframe) return;

  this.iframe = document.createElement('iframe');
  this.iframe.src = this.src;
  this.iframe.addEventListener('message', this.handleMessage.bind(this));
  this.iframe.setAttribute('allowfullscreen', 'allowfullscreen');

  this.appendChild(this.iframe);

  this.assetInput     = createAssetInput();
  this.loadingOverlay = createLoadingOverlay();
  this.assetDropzone  = createAssetDropzone();

  this.appendChild(this.assetInput);
  this.appendChild(this.assetDropzone);
  this.appendChild(this.loadingOverlay);
};

prototype.detachedCallback = function(){
  this.removeChild(this.iframe);
  this.iframe = null;
  this.removeChild(this.assetInput);
  this.removeChild(this.assetDropzone);
  this.removeChild(this.loadingOverlay);
  this._reset();
};

prototype._reset = function(){
  this._previousMessages = {};
  window.clearTimeout(this._attributesChangedTimeout);
  window.clearTimeout(this._learnerStateChangedTimeout);
};

prototype.attributeChangedCallback = function(name, oldAttribute, newAttribute){
  switch(name) {
    case 'editable':
      this.sendMessage('editableChanged', { editable: this.editable });
      if(this.apiVersion.minor < 1) {
        this.sendMessage('setEditable', { editable: this.editable });
      }
      if (this.assetDropzone) { this.hideAssetDropzone(); }
      break;

    case 'data-config':
      window.clearTimeout(this._attributesChangedTimeout);
      this._attributesChangedTimeout = window.setTimeout((function() {
        this.sendMessage('attributesChanged', this.config);
      }).bind(this));
      break;

    case 'data-userstate':
      window.clearTimeout(this._learnerStateChangedTimeout);
      this._learnerStateChangedTimeout = window.setTimeout((function() {
        this.sendMessage('learnerStateChanged', this.userstate);
      }).bind(this));
      break;
  }
};

prototype.handleMessage = function(event) {
  if(event.detail.event) {
    var eventName = event.detail.event;
    var data = event.detail.data;

    this.log('↖', eventName, data);

    var handler = this.messageHandlers[eventName];
    if(handler) {
      handler.call(this, data);
    } else {
      console.error('Unknown event received: ' + eventName);
      this.error({message: 'Unknown event received: ' + eventName});
    }
  }
};

prototype.sendMessage = function(eventName, data) {
  if (!this._listening) return;
  if (JSONDeepEquals(this._previousMessages[eventName], data)) return;

  var message = { event: eventName };
  if(data) { message.data = data; }
  if(this.iframe && this.iframe.contentWindow) {
    this.iframe.contentWindow.postMessage(message, '*');
    this.log('↘', message.event, message.data);
    this._previousMessages[eventName] = data;
  }
};

prototype.fireCustomEvent = function(eventName, data, options) {
  options = options || {};
  var evt = new CustomEvent(eventName, { detail: data, bubbles: options.bubbles || false });
  this.dispatchEvent(evt);
};

prototype.hideAssetDropzone = function() {
  this.assetDropzone.className = 'asset-dropzone hidden';
  this.assetDropzone.removeEventListener('drop', this.onDropAssetDropzone);
  this.assetDropzone.removeEventListener('dragover', onDragOverDropzone);
};

prototype.onDropAssetDropzone = function(data, event) {
  event.stopPropagation();
  event.preventDefault();
  var dataTransfer = event.dataTransfer;

  if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
    this.uploadAssetAndSetAttributes(data, dataTransfer.files[0]);
  }
};

prototype.setupDropzoneHandlers = function(requestData) {
  this.assetDropzone.onclick = function() {
    this.assetInput.click();
  }.bind(this);

  this.querySelector('.dropzone-cancel-dialog').onclick = function(event) {
    event.preventDefault();
    event.stopPropagation();
    this.hideAssetDropzone();
  }.bind(this);

  this.assetDropzone.addEventListener('dragover', onDragOverDropzone, false);
  this.assetDropzone.addEventListener('drop', this.onDropAssetDropzone.bind(this, requestData), false);
};

prototype.uploadAssetAndSetAttributes = function(data, file) {
  var apiUrl      = this.env.apiUrl,
      sessionId   = this.env.sessionId,
      serializedFile = serializeFile(file);

  if (!serializedFile) { return; }

  // To patch attributesChanged if author toggles out of gadget editing
  this.uploadingAsset = true;

  this.assetDropzone.className  = 'asset-dropzone hidden';
  this.loadingOverlay.className = 'asset-loading-overlay';

  postAsset(apiUrl, sessionId, serializedFile, function(error, assetJson) {
    this.loadingOverlay.className = 'asset-loading-overlay hidden';
    if (error) {
      return alert(error.message);
    }

    assetAttributes = {};
    assetAttributes[data.attribute] = assetJson;

    this.sendMessage('attributesChanged', assetAttributes);
    // After a period of time allotted to communicate the change to 'attributesChanged'
    // set uploadingAsset to false
    setTimeout(function() { this.uploadingAsset = false; }.bind(this), 1000);
  }.bind(this));
};

prototype.messageHandlers = {
  startListening: function(){
    this._reset();
    this._listening = true;
    this.sendMessage('environmentChanged', this.env);
    this.sendMessage('attributesChanged', this.config);
    this.sendMessage('learnerStateChanged', this.userstate);
    this.sendMessage('editableChanged', { editable: this.editable });
  },

  setHeight: function(data){
    this.iframe.style.height = data.pixels + 'px';
    if (!this._firedRendered) {
      this._firedRendered = true;
      this.fireCustomEvent('rendered');
    }
  },

  setAttributes: function(data){
    if(!this.editable && !this.uploadingAsset) {
      console.warn('Unable to setAttributes in the read-only state');
      return;
    }
    var config = this.readAttributeAsJson('data-config');
    patch(config, data);
    this.setAttribute('data-config', JSON.stringify(config));

    // Player needs those events, until we have mutation observers in place
    this.fireCustomEvent('setAttributes', config);
  },

  setLearnerState: function(data) {
    var userstate = this.readAttributeAsJson('data-userstate');
    patch(userstate, data);
    this.setAttribute('data-userstate', JSON.stringify(userstate));

    // Player needs those events, until we have mutation observers in place
    this.fireCustomEvent('setLearnerState', userstate);
  },

  getPath: function(data) {
    console.warn('getPath/setPath are obsolete');
    var assetUrlTemplate = this.env && this.env.assetUrlTemplate;
    if(assetUrlTemplate) {
      var url = assetUrlTemplate.replace('<%= id %>', data.assetId );
      this.sendMessage('setPath', { url: url});
    }
  },

  setPropertySheetAttributes: function(data) { this.fireCustomEvent('setPropertySheetAttributes', data); },
  track: function(data) { this.fireCustomEvent('track', data, {bubbles: true}); },
  error: function(data) { this.fireCustomEvent('error', data, {bubbles: true}); },
  requestAsset: function(data) {
    // TODO support other updload types
    if (data.type == 'video') {
      return this.fireCustomEvent('requestAsset', data);
    }

    this.assetDropzone.className = 'asset-dropzone';
    this.setupDropzoneHandlers(data);

    this.assetInput.onchange = function(e) {
      if (e && e.target && e.target.files && e.target.files[0]) {
        this.uploadAssetAndSetAttributes(data, e.target.files[0]);
      }
    }.bind(this);
  },

  // Soon to be deprecated in favour of in-iframe APIs
  // E.g. https://github.com/Versal/challenges-js-api/
  setEmpty: function(data) { this.fireCustomEvent('setEmpty', data); },
  changeBlocking: function(data) { this.fireCustomEvent('changeBlocking', data); }
};

window.addEventListener('message', function(event){
  var iframes = document.querySelectorAll('versal-iframe-launcher > iframe');
  Array.prototype.forEach.call(iframes, function(iframe){
    if(iframe.contentWindow == event.source) {
      iframe.dispatchEvent(new CustomEvent('message', { detail: event.data }));
    }
  });
});

document.registerElement('versal-iframe-launcher', { prototype: prototype });
<|endoftext|>


<commit_before>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * control-input function
 *
 * Control inputs include radio buttons and checkboxes. They allow users to select one or more options.
 *
 **************************************************************************************************************************************************************/

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';

// The following line will be replaced automatically with generic imports for the ES5 pipeline.
// You can safely ignore this bit if you use this module with pancake
//
// [replace-imports]

/**
 * The checkbox component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} alt              - Add the alt variation class, optional
 * @param  {boolean} small            - Add the small variation class
 * @param  {boolean} block            - Add the block variation class
 * @param  {string}  label            - The label
 * @param  {string}  status           - Mark this field as either 'valid' or 'invalid', optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 *
 */
export const AUcheckbox = ({ dark, alt, small, block, label, status, id, className = '', ...attributeOptions }) => {
	return (
		<div className={
			`au-control-input ${ className }` +
			`${ dark ? ' au-control-input--dark' : '' }` +
			`${ alt ? ' au-control-input--alt' : '' }` +
			`${ small ? ' au-control-input--small' : '' }` +
			`${ block ? ` au-control-input--block` : '' }` +
			`${ status === 'valid' ? ' au-control-input--valid' : '' }` +
			`${ status === 'invalid' ? ' au-control-input--invalid' : '' }`
		}>
			<input className="au-control-input__input" id={ id } type="checkbox" { ...attributeOptions } />
			{ label }

	);
};

AUcheckbox.propTypes = {
	dark: PropTypes.bool,
	alt: PropTypes.bool,
	small: PropTypes.bool,
	block: PropTypes.bool,
	label: PropTypes.string.isRequired,
	id: PropTypes.string.isRequired,
	status: PropTypes.oneOf([ 'valid', 'invalid' ]),
	className: PropTypes.string,
};

/**
 * The radio component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} alt              - Add the alt variation class, optional
 * @param  {boolean} small            - Add the small variation class
 * @param  {boolean} block            - Add the block variation class
 * @param  {string}  label            - The label
 * @param  {string}  status           - Mark this field as either 'valid' or 'invalid', optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUradio = ({ dark, alt, small, block, label, status, id, className = '', ...attributeOptions }) => {

	return (
		<div className={
			`au-control-input ${ className }` +
			`${ dark ? ` au-control-input--dark` : '' }` +
			`${ alt ? ` au-control-input--alt` : '' }` +
			`${ small ? ` au-control-input--small` : '' }` +
			`${ block ? ` au-control-input--block` : '' }` +
			`${ status === 'valid' ? ' au-control-input--valid' : '' }` +
			`${ status === 'invalid' ? ' au-control-input--invalid' : '' }`
		} >
			<input className="au-control-input__input" type="radio" id= { id } { ...attributeOptions } />
			{ label }

	);
};

AUradio.propTypes = {
	dark: PropTypes.bool,
	alt: PropTypes.bool,
	small: PropTypes.bool,
	block: PropTypes.bool,
	label: PropTypes.string.isRequired,
	id: PropTypes.string.isRequired,
	status: PropTypes.oneOf([ 'valid', 'invalid' ]),
	className: PropTypes.string,
};<commit_msg>add param<commit_after>/*! [replace-name] v[replace-version] */
/***************************************************************************************************************************************************************
 *
 * control-input function
 *
 * Control inputs include radio buttons and checkboxes. They allow users to select one or more options.
 *
 **************************************************************************************************************************************************************/

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';

// The following line will be replaced automatically with generic imports for the ES5 pipeline.
// You can safely ignore this bit if you use this module with pancake
//
// [replace-imports]

/**
 * The checkbox component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} alt              - Add the alt variation class, optional
 * @param  {boolean} small            - Add the small variation class
 * @param  {boolean} block            - Add the block variation class
 * @param  {string}  label            - The label
 * @param  {id}      id               - The id for the control input
 * @param  {string}  status           - Mark this field as either 'valid' or 'invalid', optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 *
 */
export const AUcheckbox = ({ dark, alt, small, block, label, status, id, className = '', ...attributeOptions }) => {
	return (
		<div className={
			`au-control-input ${ className }` +
			`${ dark ? ' au-control-input--dark' : '' }` +
			`${ alt ? ' au-control-input--alt' : '' }` +
			`${ small ? ' au-control-input--small' : '' }` +
			`${ block ? ` au-control-input--block` : '' }` +
			`${ status === 'valid' ? ' au-control-input--valid' : '' }` +
			`${ status === 'invalid' ? ' au-control-input--invalid' : '' }`
		}>
			<input className="au-control-input__input" id={ id } type="checkbox" { ...attributeOptions } />
			{ label }

	);
};

AUcheckbox.propTypes = {
	dark: PropTypes.bool,
	alt: PropTypes.bool,
	small: PropTypes.bool,
	block: PropTypes.bool,
	label: PropTypes.string.isRequired,
	id: PropTypes.string.isRequired,
	status: PropTypes.oneOf([ 'valid', 'invalid' ]),
	className: PropTypes.string,
};

/**
 * The radio component
 *
 * @param  {boolean} dark             - Add the dark variation class, optional
 * @param  {boolean} alt              - Add the alt variation class, optional
 * @param  {boolean} small            - Add the small variation class
 * @param  {boolean} block            - Add the block variation class
 * @param  {string}  label            - The label
 * @param  {string}  status           - Mark this field as either 'valid' or 'invalid', optional
 * @param  {string}  className        - An additional class, optional
 * @param  {object}  attributeOptions - Any other attribute options
 */
export const AUradio = ({ dark, alt, small, block, label, status, id, className = '', ...attributeOptions }) => {

	return (
		<div className={
			`au-control-input ${ className }` +
			`${ dark ? ` au-control-input--dark` : '' }` +
			`${ alt ? ` au-control-input--alt` : '' }` +
			`${ small ? ` au-control-input--small` : '' }` +
			`${ block ? ` au-control-input--block` : '' }` +
			`${ status === 'valid' ? ' au-control-input--valid' : '' }` +
			`${ status === 'invalid' ? ' au-control-input--invalid' : '' }`
		} >
			<input className="au-control-input__input" type="radio" id= { id } { ...attributeOptions } />
			{ label }

	);
};

AUradio.propTypes = {
	dark: PropTypes.bool,
	alt: PropTypes.bool,
	small: PropTypes.bool,
	block: PropTypes.bool,
	label: PropTypes.string.isRequired,
	id: PropTypes.string.isRequired,
	status: PropTypes.oneOf([ 'valid', 'invalid' ]),
	className: PropTypes.string,
};<|endoftext|>


<commit_before>'use strict';

const SVGO = require('svgo');
const svg2js = require('svgo/lib/svgo/svg2js');

const plugins = [
  {
    removeTransparentRectangle: {
      type: 'perItem',
      description: 'removes transparent rectangles used for bounding box',
      fn(item) {
        // Two potential situations can happen if we have a bounding Transparent
        // Rectangle, namly the node has a `<rect>` element for the rectangle or
        // the group has valid content inside of it. As a result, we can return
        // the content and then have multipass remove the `<rect>` if that is
        // what is contained inside.
        if (item.isElem('g') && item.attr('id', 'Transparent_Rectangle')) {
          return item.content;
        }

        if (
          item.isElem('rect') &&
          item.attr('width', '32') &&
          item.attr('height', '32')
        ) {
          return !item;
        }

        if (
          item.isElem('rect') &&
          item.attr('width', '16') &&
          item.attr('height', '16')
        ) {
          return !item;
        }

        return item;
      },
    },
  },
  {
    inlineStyles: {
      onlyMatchedOnce: false,
      removeMatchedSelectors: true,
      useMqs: ['', 'screen'],
      usePseudos: [''],
    },
  },
  // Remove the style elements from the SVG
  {
    removeStyleElement: true,
  },
  {
    cleanupAttrs: true,
  },
  {
    removeDoctype: true,
  },
  {
    removeXMLProcInst: true,
  },
  {
    removeComments: true,
  },
  {
    removeMetadata: true,
  },
  {
    // Remove any title tags because titles should be based on the context of
    // the SVG.
    removeTitle: true,
  },
  {
    removeDesc: true,
  },
  {
    removeUselessDefs: true,
  },
  {
    removeEditorsNSData: true,
  },
  {
    removeEmptyAttrs: true,
  },
  {
    removeHiddenElems: true,
  },
  {
    removeEmptyText: true,
  },
  {
    removeEmptyContainers: true,
  },
  {
    removeViewBox: false,
  },
  {
    cleanupEnableBackground: true,
  },
  {
    convertStyleToAttrs: true,
  },
  {
    convertColors: true,
  },
  {
    convertPathData: true,
  },
  {
    convertTransform: true,
  },
  {
    removeUnknownsAndDefaults: true,
  },
  {
    removeNonInheritableGroupAttrs: true,
  },
  {
    removeUselessStrokeAndFill: true,
  },
  {
    removeUnusedNS: true,
  },
  {
    cleanupIDs: true,
  },
  {
    cleanupNumericValues: true,
  },
  {
    moveElemsAttrsToGroup: true,
  },
  {
    moveGroupAttrsToElems: true,
  },
  {
    collapseGroups: true,
  },
  {
    removeRasterImages: false,
  },
  {
    mergePaths: true,
  },
  {
    convertShapeToPath: true,
  },
  {
    sortAttrs: true,
  },
  {
    removeDimensions: true,
  },
  {
    // Remove any ids or data attributes that are included in SVG source files.
    removeAttrs: {
      attrs: ['class', 'data-name', 'id'],
    },
  },
];

const svgo = new SVGO({
  plugins,
  full: true,
  multipass: true,
});

const svg2jsAsync = (...args) =>
  new Promise((resolve, reject) => {
    svg2js(...args, ({ error, ...rest }) => {
      if (error) {
        reject(error);
        return;
      }
      resolve(rest);
    });
  });

const parse = async (svg, name) => {
  const root = await svg2jsAsync(svg);
  try {
    return convert(root.content[0]);
  } catch (error) {
    // eslint-disable-next-line no-console
    console.log(error);
    // eslint-disable-next-line no-console
    console.log(`Error parsing icon with name: ${name}`);
  }
};

const convert = root => {
  const { elem, attrs = {}, content } = root;
  const safeFormat = {
    elem,
    attrs: Object.keys(attrs).reduce((acc, attr) => {
      return {
        ...acc,
        [attr]: attrs[attr].value,
      };
    }, {}),
  };

  if (content) {
    safeFormat.content = content.map(convert);
  }

  return safeFormat;
};

module.exports = {
  svgo,
  plugins,
  svg2js: svg2jsAsync,
  parse,
};
<commit_msg>fix(icons): add fill attribute to remove list in optimize pass (#91)<commit_after>'use strict';

const SVGO = require('svgo');
const svg2js = require('svgo/lib/svgo/svg2js');

const plugins = [
  {
    removeTransparentRectangle: {
      type: 'perItem',
      description: 'removes transparent rectangles used for bounding box',
      fn(item) {
        // Two potential situations can happen if we have a bounding Transparent
        // Rectangle, namly the node has a `<rect>` element for the rectangle or
        // the group has valid content inside of it. As a result, we can return
        // the content and then have multipass remove the `<rect>` if that is
        // what is contained inside.
        if (item.isElem('g') && item.attr('id', 'Transparent_Rectangle')) {
          return item.content;
        }

        if (
          item.isElem('rect') &&
          item.attr('width', '32') &&
          item.attr('height', '32')
        ) {
          return !item;
        }

        if (
          item.isElem('rect') &&
          item.attr('width', '16') &&
          item.attr('height', '16')
        ) {
          return !item;
        }

        return item;
      },
    },
  },
  {
    inlineStyles: {
      onlyMatchedOnce: false,
      removeMatchedSelectors: true,
      useMqs: ['', 'screen'],
      usePseudos: [''],
    },
  },
  // Remove the style elements from the SVG
  {
    removeStyleElement: true,
  },
  {
    cleanupAttrs: true,
  },
  {
    removeDoctype: true,
  },
  {
    removeXMLProcInst: true,
  },
  {
    removeComments: true,
  },
  {
    removeMetadata: true,
  },
  {
    // Remove any title tags because titles should be based on the context of
    // the SVG.
    removeTitle: true,
  },
  {
    removeDesc: true,
  },
  {
    removeUselessDefs: true,
  },
  {
    removeEditorsNSData: true,
  },
  {
    removeEmptyAttrs: true,
  },
  {
    removeHiddenElems: true,
  },
  {
    removeEmptyText: true,
  },
  {
    removeEmptyContainers: true,
  },
  {
    removeViewBox: false,
  },
  {
    cleanupEnableBackground: true,
  },
  {
    convertStyleToAttrs: true,
  },
  {
    convertColors: true,
  },
  {
    convertPathData: true,
  },
  {
    convertTransform: true,
  },
  {
    removeUnknownsAndDefaults: true,
  },
  {
    removeNonInheritableGroupAttrs: true,
  },
  {
    removeUselessStrokeAndFill: true,
  },
  {
    removeUnusedNS: true,
  },
  {
    cleanupIDs: true,
  },
  {
    cleanupNumericValues: true,
  },
  {
    moveElemsAttrsToGroup: true,
  },
  {
    moveGroupAttrsToElems: true,
  },
  {
    collapseGroups: true,
  },
  {
    removeRasterImages: false,
  },
  {
    mergePaths: true,
  },
  {
    convertShapeToPath: true,
  },
  {
    sortAttrs: true,
  },
  {
    removeDimensions: true,
  },
  {
    // Remove any ids or data attributes that are included in SVG source files.
    removeAttrs: {
      attrs: ['class', 'data-name', 'fill', 'id'],
    },
  },
];

const svgo = new SVGO({
  plugins,
  full: true,
  multipass: true,
});

const svg2jsAsync = (...args) =>
  new Promise((resolve, reject) => {
    svg2js(...args, ({ error, ...rest }) => {
      if (error) {
        reject(error);
        return;
      }
      resolve(rest);
    });
  });

const parse = async (svg, name) => {
  const root = await svg2jsAsync(svg);
  try {
    return convert(root.content[0]);
  } catch (error) {
    // eslint-disable-next-line no-console
    console.log(error);
    // eslint-disable-next-line no-console
    console.log(`Error parsing icon with name: ${name}`);
  }
};

const convert = root => {
  const { elem, attrs = {}, content } = root;
  const safeFormat = {
    elem,
    attrs: Object.keys(attrs).reduce((acc, attr) => {
      return {
        ...acc,
        [attr]: attrs[attr].value,
      };
    }, {}),
  };

  if (content) {
    safeFormat.content = content.map(convert);
  }

  return safeFormat;
};

module.exports = {
  svgo,
  plugins,
  svg2js: svg2jsAsync,
  parse,
};
<|endoftext|>


<commit_before>import EmbarkAPI from 'embark-api-client';

const embarkAPI = new EmbarkAPI()

export function postCommand() {
  return embarkAPI.postCommand(...arguments)
}

export function postCommandSuggestions() {
  return embarkAPI.postCommandSuggestions(...arguments);
}

export function fetchAccounts() {
  return embarkAPI.fetchAccounts(...arguments);
}

export function fetchAccount(payload) {
  return embarkAPI.fetchAccount(payload, ...arguments);
}

export function fetchBlocks(payload) {
  return embarkAPI.fetchBlocks(payload);
}

export function fetchBlock(payload) {
  return embarkAPI.fetchBlock(payload, ...arguments);
}

export function fetchTransactions(payload) {
  return embarkAPI.fetchTransactions(payload);
}

export function fetchTransaction(payload) {
  return embarkAPI.fetchTransaction(payload, ...arguments);
}

export function fetchProcesses() {
  return embarkAPI.fetchProcesses(...arguments);
}

export function fetchServices() {
  return embarkAPI.fetchServices(...arguments);
}

export function fetchProcessLogs(payload) {
  return embarkAPI.fetchProcessLogs(payload);
}

export function fetchContractLogs() {
  return embarkAPI.fetchContractLogs(...arguments);
}

export function fetchContractEvents() {
  return embarkAPI.fetchContractEvents(...arguments);
}

export function fetchContracts() {
  return embarkAPI.fetchContracts(...arguments);
}

export function fetchContract(payload) {
  return embarkAPI.fetchContract(payload, ...arguments);
}

export function postContractFunction(payload) {
  return embarkAPI.postContractFunction(payload, ...arguments);
}

export function postContractDeploy(payload) {
  return embarkAPI.postContractDeploy(payload, ...arguments);
}

export function postContractCompile() {
  return embarkAPI.postContractCompile(...arguments);
}

export function fetchVersions() {
  return embarkAPI.fetchVersions(...arguments);
}

export function fetchPlugins() {
  return embarkAPI.fetchPlugins(...arguments);
}

export function sendMessage(payload) {
  return embarkAPI.sendMessage(payload);
}

export function fetchContractProfile(payload) {
  return embarkAPI.fetchContractProfile(payload, ...arguments);
}

export function fetchEnsRecord(payload) {
  return embarkAPI.fetchEnsRecord(payload);
}

export function postEnsRecord() {
  return embarkAPI.postEnsRecord(...arguments);
}

export function getEthGasAPI() {
  return embarkAPI.getEthGasAPI(...arguments);
}

export function fetchFiles() {
  return embarkAPI.fetchFiles(...arguments);
}

export function fetchFile(payload) {
  return embarkAPI.fetchFile(payload);
}

export function postFile() {
  return embarkAPI.postFile(...arguments);
}

export function postFolder() {
  return embarkAPI.postFolder(...arguments);
}

export function deleteFile(payload) {
  return embarkAPI.deleteFile(payload);
}

export function authenticate(payload) {
  return embarkAPI.authenticate(payload);
}

export function signMessage(payload) {
  return embarkAPI.signMessage(payload, ...arguments);
}

export function verifyMessage(payload) {
  return embarkAPI.verifyMessage(payload, ...arguments);
}

export function startDebug(payload) {
  return embarkAPI.startDebug(payload);
}

export function stopDebug(payload) {
  return embarkAPI.stopDebug(payload);
}

export function debugJumpBack(payload) {
  return embarkAPI.debugJumpBack(payload);
}

export function debugJumpForward(payload) {
  return embarkAPI.debugJumpForward(payload);
}

export function debugStepOverForward(payload) {
  return embarkAPI.debugStepOverForward(payload);
}

export function debugStepOverBackward(payload) {
  return embarkAPI.debugStepOverBackward(payload);
}

export function debugStepIntoForward(payload) {
  return embarkAPI.debugStepIntoForward(payload);
}

export function debugStepIntoBackward(payload) {
  return embarkAPI.debugStepIntoBackward(payload);
}

export function toggleBreakpoint(payload) {
  return embarkAPI.toggleBreakpoint(payload);
}

export function listenToDebugger(credentials) {
  return embarkAPI.listenToDebugger(credentials, '/debugger');
}

export function listenToChannel(credentials, channel) {
  return embarkAPI.listenToChannel(credentials, `/communication/listenTo/${channel}`);
}

export function webSocketProcess(credentials, processName) {
  return embarkAPI.webSocketProcess(credentials, processName);
}

export function webSocketServices(credentials) {
  return embarkAPI.webSocketServices(credentials, `/services`);
}

export function webSocketContractLogs(credentials) {
  return embarkAPI.webSocketContractLogs(credentials, `/contracts/logs`);
}

export function webSocketContracts(credentials) {
  return embarkAPI.webSocketContracts(credentials, `/contracts`);
}

export function webSocketContractEvents(credentials) {
  return embarkAPI.webSocketContractEvents(credentials, `/blockchain/contracts/event`);
}

export function webSocketBlockHeader(credentials) {
  return embarkAPI.webSocketBlockHeader(credentials, `/blockchain/blockHeader`);
}

export function websocketGasOracle(credentials) {
  return embarkAPI.websocketGasOracle(credentials, `/blockchain/gas/oracle`);
}
<commit_msg>fix(@cockpit/whisper): ensure message subscription call is working<commit_after>import EmbarkAPI from 'embark-api-client';

const embarkAPI = new EmbarkAPI()

export function postCommand() {
  return embarkAPI.postCommand(...arguments)
}

export function postCommandSuggestions() {
  return embarkAPI.postCommandSuggestions(...arguments);
}

export function fetchAccounts() {
  return embarkAPI.fetchAccounts(...arguments);
}

export function fetchAccount(payload) {
  return embarkAPI.fetchAccount(payload, ...arguments);
}

export function fetchBlocks(payload) {
  return embarkAPI.fetchBlocks(payload);
}

export function fetchBlock(payload) {
  return embarkAPI.fetchBlock(payload, ...arguments);
}

export function fetchTransactions(payload) {
  return embarkAPI.fetchTransactions(payload);
}

export function fetchTransaction(payload) {
  return embarkAPI.fetchTransaction(payload, ...arguments);
}

export function fetchProcesses() {
  return embarkAPI.fetchProcesses(...arguments);
}

export function fetchServices() {
  return embarkAPI.fetchServices(...arguments);
}

export function fetchProcessLogs(payload) {
  return embarkAPI.fetchProcessLogs(payload);
}

export function fetchContractLogs() {
  return embarkAPI.fetchContractLogs(...arguments);
}

export function fetchContractEvents() {
  return embarkAPI.fetchContractEvents(...arguments);
}

export function fetchContracts() {
  return embarkAPI.fetchContracts(...arguments);
}

export function fetchContract(payload) {
  return embarkAPI.fetchContract(payload, ...arguments);
}

export function postContractFunction(payload) {
  return embarkAPI.postContractFunction(payload, ...arguments);
}

export function postContractDeploy(payload) {
  return embarkAPI.postContractDeploy(payload, ...arguments);
}

export function postContractCompile() {
  return embarkAPI.postContractCompile(...arguments);
}

export function fetchVersions() {
  return embarkAPI.fetchVersions(...arguments);
}

export function fetchPlugins() {
  return embarkAPI.fetchPlugins(...arguments);
}

export function sendMessage(payload) {
  return embarkAPI.sendMessage(payload);
}

export function fetchContractProfile(payload) {
  return embarkAPI.fetchContractProfile(payload, ...arguments);
}

export function fetchEnsRecord(payload) {
  return embarkAPI.fetchEnsRecord(payload);
}

export function postEnsRecord() {
  return embarkAPI.postEnsRecord(...arguments);
}

export function getEthGasAPI() {
  return embarkAPI.getEthGasAPI(...arguments);
}

export function fetchFiles() {
  return embarkAPI.fetchFiles(...arguments);
}

export function fetchFile(payload) {
  return embarkAPI.fetchFile(payload);
}

export function postFile() {
  return embarkAPI.postFile(...arguments);
}

export function postFolder() {
  return embarkAPI.postFolder(...arguments);
}

export function deleteFile(payload) {
  return embarkAPI.deleteFile(payload);
}

export function authenticate(payload) {
  return embarkAPI.authenticate(payload);
}

export function signMessage(payload) {
  return embarkAPI.signMessage(payload, ...arguments);
}

export function verifyMessage(payload) {
  return embarkAPI.verifyMessage(payload, ...arguments);
}

export function startDebug(payload) {
  return embarkAPI.startDebug(payload);
}

export function stopDebug(payload) {
  return embarkAPI.stopDebug(payload);
}

export function debugJumpBack(payload) {
  return embarkAPI.debugJumpBack(payload);
}

export function debugJumpForward(payload) {
  return embarkAPI.debugJumpForward(payload);
}

export function debugStepOverForward(payload) {
  return embarkAPI.debugStepOverForward(payload);
}

export function debugStepOverBackward(payload) {
  return embarkAPI.debugStepOverBackward(payload);
}

export function debugStepIntoForward(payload) {
  return embarkAPI.debugStepIntoForward(payload);
}

export function debugStepIntoBackward(payload) {
  return embarkAPI.debugStepIntoBackward(payload);
}

export function toggleBreakpoint(payload) {
  return embarkAPI.toggleBreakpoint(payload);
}

export function listenToDebugger(credentials) {
  return embarkAPI.listenToDebugger(credentials);
}

export function listenToChannel(credentials, channel) {
  return embarkAPI.listenToChannel(credentials, channel);
}

export function webSocketProcess(credentials, processName) {
  return embarkAPI.webSocketProcess(credentials, processName);
}

export function webSocketServices(credentials) {
  return embarkAPI.webSocketServices(credentials);
}

export function webSocketContractLogs(credentials) {
  return embarkAPI.webSocketContractLogs(credentials);
}

export function webSocketContracts(credentials) {
  return embarkAPI.webSocketContracts(credentials);
}

export function webSocketContractEvents(credentials) {
  return embarkAPI.webSocketContractEvents(credentials);
}

export function webSocketBlockHeader(credentials) {
  return embarkAPI.webSocketBlockHeader(credentials);
}

export function websocketGasOracle(credentials) {
  return embarkAPI.websocketGasOracle(credentials);
}
<|endoftext|>


<commit_before>var predictionio = require('predictionio-driver');
var models = require('../../../models');
var _ = require('lodash');
var async = require('async');
var log = require('../../../utils/logger');

var ACTIVE_CITIZEN_PIO_APP_ID = 1;

var getClient = function (appId) {
  return new predictionio.Events({appId: appId});
};

var lineCrCounter = 0;

var convertToString = function(integer) {
  return integer.toString();
};

var processDots = function() {
  if (lineCrCounter>242) {
    process.stdout.write("\n");
    lineCrCounter = 1;
  } else {
    process.stdout.write(".");
    lineCrCounter += 1;
  }
};

var importAllUsers = function (done) {
  var client = getClient(1);

  log.info('AcImportAllUsers', {});
  lineCrCounter = 0;
  models.User.findAll(
    {
      attributes: ['id','notifications_settings','email','name','created_at']
    }).then(function (users) {
    async.eachSeries(users, function (user, callback) {
      client.createUser( {
        appId: 1,
        uid: user.id,
        eventTime: user.created_at.toISOString()
      }).then(function(result) {
        processDots();
        //console.log(result);
        callback();
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("\n FIN");
      done();
    });
  });
};

var importFollowings = function (done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);

  log.info('AcImportFollowings', {});
  lineCrCounter = 0;
  models.AcFollowing.findAll({
  }).then(function (followings) {
    async.eachSeries(followings, function (following, callback) {
      client.createAction({
        event: 'user-following',
        entityId: following.user_id,
        targetEntityId: following.other_user_id,
        targetEntityType: 'user',
        date: following.created_at.toISOString(),
        eventTime: following.created_at.toISOString()
      }).then(function(result) {
        processDots();
        callback();
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("\n FIN");
      done();
    });
  });
};

var updateAllPosts = function (done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);
  log.info('AcImportAllPosts', {});

  models.Post.unscoped().findAll(
    {
      include: [
        {
          model: models.Point,
          required: false,
          where: {
            status: 'published'
          }
        },
        {
          model: models.Category,
          required: false
        },
        {
          model: models.Group,
          required: true,
          where: {
            access: models.Group.ACCESS_PUBLIC
          },
          include: [
            {
              model: models.Community,
              required: true,
              where: {
                access: models.Community.ACCESS_PUBLIC
              },
              include: [
                {
                  model: models.Domain,
                  required: true
                }
              ]
            }
          ]
        }
      ]
    }).then(function (posts) {
    lineCrCounter = 0;
    async.eachSeries(posts, function (post, callback) {

      var properties = {};

      if (post.category_id) {
        properties = _.merge(properties,
          {
            category: [ convertToString(post.category_id) ]
          });
      }
      properties = _.merge(properties,
        {
          domain: [ convertToString(post.Group.Community.Domain.id) ],
          domainLocale: [ post.Group.Community.Domain.default_locale ],
          community: [ convertToString(post.Group.Community.id) ],
          communityAccess: [ convertToString(post.Group.Community.access) ],
          communityStatus: [ convertToString(post.Group.Community.status) ],
          communityLocale: [ (post.Group.Community.default_locale && post.Group.Community.default_locale!='')  ?
                               post.Group.Community.default_locale :
                               post.Group.Community.Domain.default_locale ],
          group: [ convertToString(post.Group.id) ],
          groupAccess: [ convertToString(post.Group.access) ],
          groupStatus: [ convertToString(post.Group.status) ],
          status: [ post.deleted ? 'deleted' : post.status ],
          official_status: [ convertToString(post.official_status) ]
        });

      properties = _.merge(properties,
        {
          date: post.created_at.toISOString()
        }
      );

      client.createItem({
        entityId: post.id,
        properties: properties,
        date: post.created_at.toISOString(),
        eventTime: post.created_at.toISOString()
      }).then(function(result) {
        //  console.log(result);
        if (post.category_id && !post.deleted) {
          client.createAction({
            event: 'category-preference',
            entityId: post.user_id,
            targetEntityId :post.category_id,
            date: post.created_at.toISOString(),
            eventTime: post.created_at.toISOString()
          }).then(function(result) {
            processDots();
            callback();
          });
        } else {
          processDots();
          callback();
        }
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("Finished updating posts");
      done();
    });
  });
};

var importAllActionsFor = function (model, where, include, action, done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);
  log.info('AcImportAllActionsFor', {action:action, model: model, where: where, include: include});

  model.findAll(
    {
      where: where,
      include: include
    }
  ).then(function (objects) {
    lineCrCounter = 0;
    async.eachSeries(objects, function (object, callback) {
      var targetEntityId;
      if (action.indexOf('help') > -1) {
        targetEntityId = object.Point.Post.id;
      } else if (action.indexOf('post') > -1) {
        targetEntityId = object.id;
      } else {
        targetEntityId = object.Post.id;
      }

      if (targetEntityId) {
        client.createAction({
          event: action,
          uid: object.user_id,
          targetEntityId: targetEntityId,
          date: object.created_at.toISOString(),
          eventTime: object.created_at.toISOString()
        }).then(function(result) {
          processDots();
          //       console.log(result);
          callback();
        }).
        catch(function(error) {
          console.error(error);
          callback();
        });
      } else {
        console.error("Can't find id for object: " + object);
        callback();
      }
    }, function (error) {
      console.log(error);
      console.log("\n FIN");
      done();
    });
  });
};

var importAll = function(done) {
  async.series([
    function(callback){
      importAllActionsFor(models.Post, {}, [], 'new-post', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Endorsement, { value: { $gt: 0 } }, [ models.Post ], 'endorse', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Endorsement, { value: { $lt: 0 } }, [ models.Post ], 'oppose', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Point, { value: { $ne: 0 }}, [ models.Post ], 'new-point', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Point, { value: 0 },  [ models.Post ], 'new-point-comment', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.PointQuality, { value: { $gt: 0 } }, [{
          model: models.Point,
          include: [ models.Post ]
        }], 'point-helpful', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.PointQuality, { value: { $lt: 0 } }, [{
        model: models.Point,
        include: [ models.Post ]
      }], 'point-unhelpful', function () {
        callback();
      });
    },
    function(callback){
      updateAllPosts(function () {
        callback();
      });
    }
  ], function () {
    console.log("FIN");
    done();
  });
};

getClient(ACTIVE_CITIZEN_PIO_APP_ID).status().then(function(status) {
  console.log("status");
  console.log(status);
  log.info('AcImportStarting', {});
  if (process.argv[2] && process.argv[2]=="onlyUpdatePosts") {
    updateAllPosts(function () {
      console.log("Done updating posts");
      process.exit();
    });
  } else {
    importAll(function () {
      console.log("Done importing all");
      process.exit();
    });
  }
}).catch(function (error) {
  console.log("error");
  console.log(error);
});
<commit_msg>Fixes for recommendation import<commit_after>var predictionio = require('predictionio-driver');
var models = require('../../../models');
var _ = require('lodash');
var async = require('async');
var log = require('../../../utils/logger');

var ACTIVE_CITIZEN_PIO_APP_ID = 1;

var getClient = function (appId) {
  return new predictionio.Events({appId: appId});
};

var lineCrCounter = 0;

var convertToString = function(integer) {
  return integer.toString();
};

var processDots = function() {
  if (lineCrCounter>242) {
    process.stdout.write("\n");
    lineCrCounter = 1;
  } else {
    process.stdout.write(".");
    lineCrCounter += 1;
  }
};

var importAllUsers = function (done) {
  var client = getClient(1);

  log.info('AcImportAllUsers', {});
  lineCrCounter = 0;
  models.User.findAll(
    {
      attributes: ['id','notifications_settings','email','name','created_at']
    }).then(function (users) {
    async.eachSeries(users, function (user, callback) {
      client.createUser( {
        appId: 1,
        uid: user.id,
        eventTime: user.created_at.toISOString()
      }).then(function(result) {
        processDots();
        //console.log(result);
        callback();
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("\n FIN");
      done();
    });
  });
};

var importFollowings = function (done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);

  log.info('AcImportFollowings', {});
  lineCrCounter = 0;
  models.AcFollowing.findAll({
  }).then(function (followings) {
    async.eachSeries(followings, function (following, callback) {
      client.createAction({
        event: 'user-following',
        entityId: following.user_id,
        targetEntityId: following.other_user_id,
        targetEntityType: 'user',
        date: following.created_at.toISOString(),
        eventTime: following.created_at.toISOString()
      }).then(function(result) {
        processDots();
        callback();
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("\n FIN");
      done();
    });
  });
};

var updateAllPosts = function (done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);
  log.info('AcImportAllPosts', {});

  models.Post.unscoped().findAll(
    {
      include: [
        {
          model: models.Point,
          required: false,
          where: {
            status: 'published'
          }
        },
        {
          model: models.Category,
          required: false
        },
        {
          model: models.Group,
          required: true,
          where: {
            access: models.Group.ACCESS_PUBLIC
          },
          include: [
            {
              model: models.Community,
              required: true,
              where: {
                access: models.Community.ACCESS_PUBLIC
              },
              include: [
                {
                  model: models.Domain,
                  required: true
                }
              ]
            }
          ]
        }
      ]
    }).then(function (posts) {
    lineCrCounter = 0;
    async.eachSeries(posts, function (post, callback) {

      var properties = {};

      if (post.category_id) {
        properties = _.merge(properties,
          {
            category: [ convertToString(post.category_id) ]
          });
      }
      properties = _.merge(properties,
        {
          domain: [ convertToString(post.Group.Community.Domain.id) ],
          domainLocale: [ post.Group.Community.Domain.default_locale ],
          community: [ convertToString(post.Group.Community.id) ],
          communityAccess: [ convertToString(post.Group.Community.access) ],
          communityStatus: [ post.Group.Community.status ],
          communityLocale: [ (post.Group.Community.default_locale && post.Group.Community.default_locale!='')  ?
                               post.Group.Community.default_locale :
                               post.Group.Community.Domain.default_locale ],
          group: [ convertToString(post.Group.id) ],
          groupAccess: [ convertToString(post.Group.access) ],
          groupStatus: [ post.Group.status ],
          status: [ post.deleted ? 'deleted' : post.status ],
          official_status: [ convertToString(post.official_status) ]
        });

      properties = _.merge(properties,
        {
          date: post.created_at.toISOString()
        }
      );

      client.createItem({
        entityId: post.id,
        properties: properties,
        date: post.created_at.toISOString(),
        eventTime: post.created_at.toISOString()
      }).then(function(result) {
        //  console.log(result);
        if (post.category_id && !post.deleted) {
          client.createAction({
            event: 'category-preference',
            entityId: post.user_id,
            targetEntityId :post.category_id,
            date: post.created_at.toISOString(),
            eventTime: post.created_at.toISOString()
          }).then(function(result) {
            processDots();
            callback();
          });
        } else {
          processDots();
          callback();
        }
      }).catch(function(error) {
        console.error(error);
        callback();
      });
    }, function () {
      console.log("Finished updating posts");
      done();
    });
  });
};

var importAllActionsFor = function (model, where, include, action, done) {
  var client = getClient(ACTIVE_CITIZEN_PIO_APP_ID);
  log.info('AcImportAllActionsFor', {action:action, model: model, where: where, include: include});

  model.findAll(
    {
      where: where,
      include: include
    }
  ).then(function (objects) {
    lineCrCounter = 0;
    async.eachSeries(objects, function (object, callback) {
      var targetEntityId;
      if (action.indexOf('help') > -1) {
        targetEntityId = object.Point.Post.id;
      } else if (action.indexOf('post') > -1) {
        targetEntityId = object.id;
      } else {
        targetEntityId = object.Post.id;
      }

      if (targetEntityId) {
        client.createAction({
          event: action,
          uid: object.user_id,
          targetEntityId: targetEntityId,
          date: object.created_at.toISOString(),
          eventTime: object.created_at.toISOString()
        }).then(function(result) {
          processDots();
          //       console.log(result);
          callback();
        }).
        catch(function(error) {
          console.error(error);
          callback();
        });
      } else {
        console.error("Can't find id for object: " + object);
        callback();
      }
    }, function (error) {
      console.log(error);
      console.log("\n FIN");
      done();
    });
  });
};

var importAll = function(done) {
  async.series([
    function(callback){
      importAllActionsFor(models.Post, {}, [], 'new-post', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Endorsement, { value: { $gt: 0 } }, [ models.Post ], 'endorse', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Endorsement, { value: { $lt: 0 } }, [ models.Post ], 'oppose', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Point, { value: { $ne: 0 }}, [ models.Post ], 'new-point', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.Point, { value: 0 },  [ models.Post ], 'new-point-comment', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.PointQuality, { value: { $gt: 0 } }, [{
          model: models.Point,
          include: [ models.Post ]
        }], 'point-helpful', function () {
        callback();
      });
    },
    function(callback){
      importAllActionsFor(models.PointQuality, { value: { $lt: 0 } }, [{
        model: models.Point,
        include: [ models.Post ]
      }], 'point-unhelpful', function () {
        callback();
      });
    },
    function(callback){
      updateAllPosts(function () {
        callback();
      });
    }
  ], function () {
    console.log("FIN");
    done();
  });
};

getClient(ACTIVE_CITIZEN_PIO_APP_ID).status().then(function(status) {
  console.log("status");
  console.log(status);
  log.info('AcImportStarting', {});
  if (process.argv[2] && process.argv[2]=="onlyUpdatePosts") {
    updateAllPosts(function () {
      console.log("Done updating posts");
      process.exit();
    });
  } else {
    importAll(function () {
      console.log("Done importing all");
      process.exit();
    });
  }
}).catch(function (error) {
  console.log("error");
  console.log(error);
});
<|endoftext|>


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

  angular
    .module('brewKeeper')
    .controller('RecipeListController', RecipeListController);

  RecipeListController.$inject =
    ['$location', '$rootScope', '$routeParams', 'dataService', 'recipeService'];

  function RecipeListController(
      $location,
      $rootScope,
      $routeParams,
      dataService,
      recipeService
  ) {
    var vm = this;
    vm.isPublic = ($location.path().indexOf('/public') === 0);
    vm.listBrewIt = listBrewIt;
    vm.newRating = newRating;
    vm.rateRecipe = rateRecipe;
    vm.ratingOrderBy = ratingOrderBy;
    vm.ratings = [{max: $rootScope.maxStars}];
    vm.recipes = [];
    vm.search = search;
    vm.updateRating = updateRating;

    var localUser = vm.isPublic ? 'public' : $rootScope.username;
    var publicUrl = '/api/users/public/recipes/';
    var recipesUrl = null;

    activate();

    ////////////////////////////////////////////////////////////////////////////
    // FUNCTIONS //////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////

    /**
     * Prepare the page.
     */
    function activate() {
      if (vm.isPublic) {
        recipesUrl = publicUrl;
        if ($routeParams.username) {
          // If provided, show the public recipes for the specified user
          vm.search($routeParams.username);
          return;
        }
      } else {
        recipesUrl = '/api/users/' + $rootScope.username + '/recipes/';
      }
      // Attempt to get the recipes for this user from the cache
      vm.recipes = recipeService.getRecipes(localUser);
      // If not in the cache, get them from the API
      if (vm.recipes.length === 0) {
        dataService.get(recipesUrl)
          .then(function(response) {
            vm.recipes = recipeService.cacheRecipes(response.data);
          });
      }
    }

    /**
     * Brew a recipe in the list.
     */
    function listBrewIt(id) {
      $location.path("/" + (vm.isPublic ? 'public' : $rootScope.username) +
        "/" + id + "/brewit");
    }

    /**
     * Submit a rating for a public recipe.
     */
    function newRating(rating, recipeId) {
      // Ensure that we only take this action on public recipes
      if (!vm.isPublic) {
        return;
      }
      var providedRating = {"public_rating": rating};
      dataService.post(publicUrl + recipeId + '/ratings/', providedRating)
        // Now that we have posted, update the rating to reflect the change
        .then(function() {
          dataService.get(publicUrl + recipeId + '/')
            .then(function(response) {
              recipeService.cacheRecipes(response.data);
              vm.recipes = recipeService.getRecipes('public');
            });
        });
    }

    /**
     * Rate a recipe in the list.
     */
    function rateRecipe(rating, id) {
      // Ensure that we only take this action on private recipes
      if (vm.isPublic) {
        return;
      }
      var newRating = {"rating": rating};
      dataService.patch(recipesUrl + id + '/', newRating);
    }

    /**
     * Depending on whether this is a public page or not, supply the correct
     * rating orderBy.
     */
    function ratingOrderBy() {
      if (vm.isPublic) {
        return '-combined_rating';
      }

      return '-rating';
    }

    /**
     * Display all of the user's recipes matching the given string. If no
     * string is given, get all of the recipes at the recipes url.
     */
    function search(searchString) {
      var searchParams = '';
      if (searchString !== undefined) {
        searchParams = '?search=' + searchString;
      }
      dataService.get(recipesUrl + searchParams)
        .then(function(response) {
          vm.recipes = recipeService.cacheRecipes(response.data);
        });
    }

    /**
     * Update an existing public rating.
     */
    function updateRating(rating, ratingId, recipeId) {
      // Ensure that we only take this action on public recipes
      if (!vm.isPublic) {
        return;
      }
      var providedRating = {"public_rating": rating};
      dataService.patch(
        publicUrl + recipeId + '/ratings/' + ratingId + '/',
        providedRating);
    }
  }
})();
<commit_msg>Go back to API to get all recipes if only 1 recipe in cache<commit_after>;(function() {  // IFEE
  'use strict';

  angular
    .module('brewKeeper')
    .controller('RecipeListController', RecipeListController);

  RecipeListController.$inject =
    ['$location', '$rootScope', '$routeParams', 'dataService', 'recipeService'];

  function RecipeListController(
      $location,
      $rootScope,
      $routeParams,
      dataService,
      recipeService
  ) {
    var vm = this;
    vm.isPublic = ($location.path().indexOf('/public') === 0);
    vm.listBrewIt = listBrewIt;
    vm.newRating = newRating;
    vm.rateRecipe = rateRecipe;
    vm.ratingOrderBy = ratingOrderBy;
    vm.ratings = [{max: $rootScope.maxStars}];
    vm.recipes = [];
    vm.search = search;
    vm.updateRating = updateRating;

    var localUser = vm.isPublic ? 'public' : $rootScope.username;
    var publicUrl = '/api/users/public/recipes/';
    var recipesUrl = null;

    activate();

    ////////////////////////////////////////////////////////////////////////////
    // FUNCTIONS //////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////

    /**
     * Prepare the page.
     */
    function activate() {
      if (vm.isPublic) {
        recipesUrl = publicUrl;
        if ($routeParams.username) {
          // If provided, show the public recipes for the specified user
          vm.search($routeParams.username);
          return;
        }
      } else {
        recipesUrl = '/api/users/' + $rootScope.username + '/recipes/';
      }
      // Attempt to get the recipes for this user from the cache
      vm.recipes = recipeService.getRecipes(localUser);
      // If full set of orders not in the cache, get them from the API
      if (vm.recipes.length <= 1) {
        dataService.get(recipesUrl)
          .then(function(response) {
            vm.recipes = recipeService.cacheRecipes(response.data);
          });
      }
    }

    /**
     * Brew a recipe in the list.
     */
    function listBrewIt(id) {
      $location.path("/" + localUser + "/" + id + "/brewit/");
    }

    /**
     * Submit a rating for a public recipe.
     */
    function newRating(rating, recipeId) {
      // Ensure that we only take this action on public recipes
      if (!vm.isPublic) {
        return;
      }
      var providedRating = {"public_rating": rating};
      dataService.post(publicUrl + recipeId + '/ratings/', providedRating)
        // Now that we have posted, update the rating to reflect the change
        .then(function() {
          dataService.get(publicUrl + recipeId + '/')
            .then(function(response) {
              recipeService.cacheRecipes(response.data);
              vm.recipes = recipeService.getRecipes('public');
            });
        });
    }

    /**
     * Rate a recipe in the list.
     */
    function rateRecipe(rating, id) {
      // Ensure that we only take this action on private recipes
      if (vm.isPublic) {
        return;
      }
      var newRating = {"rating": rating};
      dataService.patch(recipesUrl + id + '/', newRating);
    }

    /**
     * Depending on whether this is a public page or not, supply the correct
     * rating orderBy.
     */
    function ratingOrderBy() {
      if (vm.isPublic) {
        return '-combined_rating';
      }

      return '-rating';
    }

    /**
     * Display all of the user's recipes matching the given string. If no
     * string is given, get all of the recipes at the recipes url.
     */
    function search(searchString) {
      var searchParams = '';
      if (searchString !== undefined) {
        searchParams = '?search=' + searchString;
      }
      dataService.get(recipesUrl + searchParams)
        .then(function(response) {
          vm.recipes = recipeService.cacheRecipes(response.data);
        });
    }

    /**
     * Update an existing public rating.
     */
    function updateRating(rating, ratingId, recipeId) {
      // Ensure that we only take this action on public recipes
      if (!vm.isPublic) {
        return;
      }
      var providedRating = {"public_rating": rating};
      dataService.patch(
        publicUrl + recipeId + '/ratings/' + ratingId + '/',
        providedRating);
    }
  }
})();
<|endoftext|>


<commit_before>import { Component, PropTypes } from "react";
import ReactMixin from "react-mixin";
import { connect } from "react-redux";
import { graphql } from "react-apollo";
import gql from "graphql-tag";

import { FeedItemSkeleton } from "../../components/loading";
import ApollosPullToRefresh from "../../components/pullToRefresh";
import FeedItem from "../../components/cards/cards.FeedItem";

import Headerable from "../../mixins/mixins.Header";
import Pageable from "../../mixins/mixins.Pageable";

import { nav as navActions } from "../../store";

import Single from "./devotions.Single";

const DEVOTIONALS_QUERY = gql`
  query getDevotionals($limit: Int!, $skip: Int!) {
    content(channel: "devotionals", limit: $limit, skip: $skip) {
      id
      entryId: id
      title
      status
      channelName
      meta {
        urlTitle
        siteId
        date
        channelId
      }
      content {
        body
        images(sizes: ["large"]) {
          fileName
          fileType
          fileLabel
          url
        }
      }
    }
  }
`;

const withDevotionals = graphql(DEVOTIONALS_QUERY, {
  options: state => ({
    variables: {
      limit: state.paging.pageSize * state.paging.page,
      skip: state.paging.skip,
    },
  }),
});

const mapStateToProps = state => ({ paging: state.paging });

@connect(mapStateToProps)
@withDevotionals
@ReactMixin.decorate(Pageable)
@ReactMixin.decorate(Headerable)
class Devotions extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    data: PropTypes.object.isRequired,
  }

  componentWillMount() {
    this.props.dispatch(navActions.setLevel("TOP"));
    this.headerAction({ title: "All Devotionals" });
  }

  handleRefresh = (resolve, reject) => {
    this.props.data.refetch()
      .then(resolve)
      .catch(reject);
  }

  renderItems = () => {
    const { content } = this.props.data;
    let items = [1, 2, 3, 4, 5];
    if (content) items = content;
    return (
      items.map((item, i) => (

          {(() => {
            if (typeof item === "number") return <FeedItemSkeleton />;
            return <FeedItem item={item} />;
          })()}

      ))
    );
  }

  render() {
    return (
      <ApollosPullToRefresh handleRefresh={this.handleRefresh}>

              {this.renderItems()}

      </ApollosPullToRefresh>
    );
  }
}

const Routes = [
  { path: "devotions", component: Devotions },
  { path: "devotions/:id", component: Single },
];

export default {
  Devotions,
  Routes,
};
<commit_msg>state to ownProps<commit_after>import { Component, PropTypes } from "react";
import ReactMixin from "react-mixin";
import { connect } from "react-redux";
import { graphql } from "react-apollo";
import gql from "graphql-tag";

import { FeedItemSkeleton } from "../../components/loading";
import ApollosPullToRefresh from "../../components/pullToRefresh";
import FeedItem from "../../components/cards/cards.FeedItem";

import Headerable from "../../mixins/mixins.Header";
import Pageable from "../../mixins/mixins.Pageable";

import { nav as navActions } from "../../store";

import Single from "./devotions.Single";

const DEVOTIONALS_QUERY = gql`
  query getDevotionals($limit: Int!, $skip: Int!) {
    content(channel: "devotionals", limit: $limit, skip: $skip) {
      id
      entryId: id
      title
      status
      channelName
      meta {
        urlTitle
        siteId
        date
        channelId
      }
      content {
        body
        images(sizes: ["large"]) {
          fileName
          fileType
          fileLabel
          url
        }
      }
    }
  }
`;

const withDevotionals = graphql(DEVOTIONALS_QUERY, {
  options: ownProps => ({
    variables: {
      limit: ownProps.paging.pageSize * ownProps.paging.page,
      skip: ownProps.paging.skip,
    },
  }),
});

const mapStateToProps = state => ({ paging: state.paging });

@connect(mapStateToProps)
@withDevotionals
@ReactMixin.decorate(Pageable)
@ReactMixin.decorate(Headerable)
class Devotions extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    data: PropTypes.object.isRequired,
  }

  componentWillMount() {
    this.props.dispatch(navActions.setLevel("TOP"));
    this.headerAction({ title: "All Devotionals" });
  }

  handleRefresh = (resolve, reject) => {
    this.props.data.refetch()
      .then(resolve)
      .catch(reject);
  }

  renderItems = () => {
    const { content } = this.props.data;
    let items = [1, 2, 3, 4, 5];
    if (content) items = content;
    return (
      items.map((item, i) => (

          {(() => {
            if (typeof item === "number") return <FeedItemSkeleton />;
            return <FeedItem item={item} />;
          })()}

      ))
    );
  }

  render() {
    return (
      <ApollosPullToRefresh handleRefresh={this.handleRefresh}>

              {this.renderItems()}

      </ApollosPullToRefresh>
    );
  }
}

const Routes = [
  { path: "devotions", component: Devotions },
  { path: "devotions/:id", component: Single },
];

export default {
  Devotions,
  Routes,
};
<|endoftext|>


<commit_before>import { get } from "ember-metal/property_get";
import { set } from "ember-metal/property_set";
import run from "ember-metal/run_loop";
import EmberView from "ember-views/views/view";

/**
@module ember
@submodule ember-routing
*/

EmberView.reopen({

  /**
    Sets the private `_outlets` object on the view.

    @method init
   */
  init: function() {
    set(this, '_outlets', {});
    this._super();
  },

  /**
    Manually fill any of a view's `{{outlet}}` areas with the
    supplied view.

    Example

    ```javascript
    var MyView = Ember.View.extend({
      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
    });
    var myView = MyView.create();
    myView.appendTo('body');
    // The html for myView now looks like:
    // <div id="ember228" class="ember-view">Child view: </div>

    var FooView = Ember.View.extend({
      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
    });
    var fooView = FooView.create();
    myView.connectOutlet('main', fooView);
    // The html for myView now looks like:
    // <div id="ember228" class="ember-view">Child view:
    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
    // </div>
    ```
    @method connectOutlet
    @param  {String} outletName A unique name for the outlet
    @param  {Object} view       An Ember.View
   */
  connectOutlet: function(outletName, view) {
    if (this._pendingDisconnections) {
      delete this._pendingDisconnections[outletName];
    }

    if (this._hasEquivalentView(outletName, view)) {
      view.destroy();
      return;
    }

    var outlets = get(this, '_outlets');
    var container = get(this, 'container');
    var router = container && container.lookup('router:main');
    var renderedName = get(view, 'renderedName');

    set(outlets, outletName, view);

    if (router && renderedName) {
      router._connectActiveView(renderedName, view);
    }
  },

  /**
    Determines if the view has already been created by checking if
    the view has the same constructor, template, and context as the
    view in the `_outlets` object.

    @private
    @method _hasEquivalentView
    @param  {String} outletName The name of the outlet we are checking
    @param  {Object} view       An Ember.View
    @return {Boolean}
   */
  _hasEquivalentView: function(outletName, view) {
    var existingView = get(this, '_outlets.'+outletName);
    return existingView &&
      existingView.constructor === view.constructor &&
      existingView.get('template') === view.get('template') &&
      existingView.get('context') === view.get('context');
  },

  /**
    Removes an outlet from the view.

    Example

    ```javascript
    var MyView = Ember.View.extend({
      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
    });
    var myView = MyView.create();
    myView.appendTo('body');
    // myView's html:
    // <div id="ember228" class="ember-view">Child view: </div>

    var FooView = Ember.View.extend({
      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
    });
    var fooView = FooView.create();
    myView.connectOutlet('main', fooView);
    // myView's html:
    // <div id="ember228" class="ember-view">Child view:
    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
    // </div>

    myView.disconnectOutlet('main');
    // myView's html:
    // <div id="ember228" class="ember-view">Child view: </div>
    ```

    @method disconnectOutlet
    @param  {String} outletName The name of the outlet to be removed
   */
  disconnectOutlet: function(outletName) {
    if (!this._pendingDisconnections) {
      this._pendingDisconnections = {};
    }
    this._pendingDisconnections[outletName] = true;
    run.once(this, '_finishDisconnections');
  },

  /**
    Gets an outlet that is pending disconnection and then
    nullifys the object on the `_outlet` object.

    @private
    @method _finishDisconnections
   */
  _finishDisconnections: function() {
    if (this.isDestroyed) return; // _outlets will be gone anyway
    var outlets = get(this, '_outlets');
    var pendingDisconnections = this._pendingDisconnections;
    this._pendingDisconnections = null;

    for (var outletName in pendingDisconnections) {
      set(outlets, outletName, null);
    }
  }
});

export default EmberView;
<commit_msg>[Bugfix beta] this isn’t observable, and turns out its costly.<commit_after>import { get } from "ember-metal/property_get";
import { set } from "ember-metal/property_set";
import run from "ember-metal/run_loop";
import EmberView from "ember-views/views/view";

/**
@module ember
@submodule ember-routing
*/

EmberView.reopen({

  /**
    Sets the private `_outlets` object on the view.

    @method init
   */
  init: function() {
    this._outlets = {};
    this._super();
  },

  /**
    Manually fill any of a view's `{{outlet}}` areas with the
    supplied view.

    Example

    ```javascript
    var MyView = Ember.View.extend({
      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
    });
    var myView = MyView.create();
    myView.appendTo('body');
    // The html for myView now looks like:
    // <div id="ember228" class="ember-view">Child view: </div>

    var FooView = Ember.View.extend({
      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
    });
    var fooView = FooView.create();
    myView.connectOutlet('main', fooView);
    // The html for myView now looks like:
    // <div id="ember228" class="ember-view">Child view:
    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
    // </div>
    ```
    @method connectOutlet
    @param  {String} outletName A unique name for the outlet
    @param  {Object} view       An Ember.View
   */
  connectOutlet: function(outletName, view) {
    if (this._pendingDisconnections) {
      delete this._pendingDisconnections[outletName];
    }

    if (this._hasEquivalentView(outletName, view)) {
      view.destroy();
      return;
    }

    var outlets = get(this, '_outlets');
    var container = get(this, 'container');
    var router = container && container.lookup('router:main');
    var renderedName = get(view, 'renderedName');

    set(outlets, outletName, view);

    if (router && renderedName) {
      router._connectActiveView(renderedName, view);
    }
  },

  /**
    Determines if the view has already been created by checking if
    the view has the same constructor, template, and context as the
    view in the `_outlets` object.

    @private
    @method _hasEquivalentView
    @param  {String} outletName The name of the outlet we are checking
    @param  {Object} view       An Ember.View
    @return {Boolean}
   */
  _hasEquivalentView: function(outletName, view) {
    var existingView = get(this, '_outlets.'+outletName);
    return existingView &&
      existingView.constructor === view.constructor &&
      existingView.get('template') === view.get('template') &&
      existingView.get('context') === view.get('context');
  },

  /**
    Removes an outlet from the view.

    Example

    ```javascript
    var MyView = Ember.View.extend({
      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
    });
    var myView = MyView.create();
    myView.appendTo('body');
    // myView's html:
    // <div id="ember228" class="ember-view">Child view: </div>

    var FooView = Ember.View.extend({
      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
    });
    var fooView = FooView.create();
    myView.connectOutlet('main', fooView);
    // myView's html:
    // <div id="ember228" class="ember-view">Child view:
    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
    // </div>

    myView.disconnectOutlet('main');
    // myView's html:
    // <div id="ember228" class="ember-view">Child view: </div>
    ```

    @method disconnectOutlet
    @param  {String} outletName The name of the outlet to be removed
   */
  disconnectOutlet: function(outletName) {
    if (!this._pendingDisconnections) {
      this._pendingDisconnections = {};
    }
    this._pendingDisconnections[outletName] = true;
    run.once(this, '_finishDisconnections');
  },

  /**
    Gets an outlet that is pending disconnection and then
    nullifys the object on the `_outlet` object.

    @private
    @method _finishDisconnections
   */
  _finishDisconnections: function() {
    if (this.isDestroyed) return; // _outlets will be gone anyway
    var outlets = get(this, '_outlets');
    var pendingDisconnections = this._pendingDisconnections;
    this._pendingDisconnections = null;

    for (var outletName in pendingDisconnections) {
      set(outlets, outletName, null);
    }
  }
});

export default EmberView;
<|endoftext|>


<commit_before>const fs = require("fs");
const path = require("path");
const Moon = require("moon");
const slash = require("./slash/slash");

const cssRE = /([@#.="':\w\s\-\[\]()]+)(\s*,|(?:{[\s\n]*(?:[\w\n]+:[\w\s\n(),]+;[\s\n]*)*}))/g;

const addClass(element, name) => {
	const attributes = element.attributes;
	let value = name;
	let expression = false;
	let dynamic = false;

	for (let i = 0; i < attributes.length; i++) {
		const attribute = attributes[i];
		if (attribute.key === "class") {
			if (attribute.expression) {
				value = `(${attribute.value}) + " ${name}"`;
				expression = attribute.expression;
				dynamic = attribute.dynamic;
			} else {
				value = `${attribute.value} ${name}`;
			}

			attributes.splice(i, 1);
			break;
		}
	}

	attributes.push({
		key: "class",
		value: value,
		expression: expression,
		dynamic: dynamic
	});
};

module.exports = (file, contents) => {
	let js = "import Moon from \"moon\";";
	let css;
	let deps = [];

	let view = "";
	let data = "{};";

	const fileName = path.basename(file).slice(0, -4);
	const directoryName = path.dirname(file);
	const name = path.basename(directoryName);

	if (fs.existsSync(path.join(directoryName, fileName + ".js"))) {
		const dep = `.${path.sep}${fileName}.js`;
		deps.push(dep);
		js += `import data from "${dep}";`;
		data = "data;";
	}

	const cssPath = path.join(directoryName, fileName + ".css");
	if (fs.existsSync(cssPath)) {
		const scope = `moon-${name}-${slash(name)}`;
		view = Moon.generate(addClass(Moon.parse(contents), scope), null);
		css = fs.readFileSync(css).toString().replace(cssRE, (match, selector, rule) => {
			return selector.replace(trailingWhitespaceRE, "") + "." + scope;
		});
	} else {
		view = Moon.compile(contents);
	}

	js += `export default Moon.extend("${name}",function(){var options=${data}options.view=function(m,instance,locals){${view}};return options;});`;

	return {
		js: js,
		css: css,
		deps: deps
	};
};
<commit_msg>require correctly<commit_after>const fs = require("fs");
const path = require("path");
const Moon = require("moon");
const slash = require("./slash/slash.js");

const cssRE = /([@#.="':\w\s\-\[\]()]+)(\s*,|(?:{[\s\n]*(?:[\w\n]+:[\w\s\n(),]+;[\s\n]*)*}))/g;

const addClass(element, name) => {
	const attributes = element.attributes;
	let value = name;
	let expression = false;
	let dynamic = false;

	for (let i = 0; i < attributes.length; i++) {
		const attribute = attributes[i];
		if (attribute.key === "class") {
			if (attribute.expression) {
				value = `(${attribute.value}) + " ${name}"`;
				expression = attribute.expression;
				dynamic = attribute.dynamic;
			} else {
				value = `${attribute.value} ${name}`;
			}

			attributes.splice(i, 1);
			break;
		}
	}

	attributes.push({
		key: "class",
		value: value,
		expression: expression,
		dynamic: dynamic
	});
};

module.exports = (file, contents) => {
	let js = "import Moon from \"moon\";";
	let css;
	let deps = [];

	let view = "";
	let data = "{};";

	const fileName = path.basename(file).slice(0, -4);
	const directoryName = path.dirname(file);
	const name = path.basename(directoryName);

	if (fs.existsSync(path.join(directoryName, fileName + ".js"))) {
		const dep = `.${path.sep}${fileName}.js`;
		deps.push(dep);
		js += `import data from "${dep}";`;
		data = "data;";
	}

	const cssPath = path.join(directoryName, fileName + ".css");
	if (fs.existsSync(cssPath)) {
		const scope = `moon-${name}-${slash(name)}`;
		view = Moon.generate(addClass(Moon.parse(contents), scope), null);
		css = fs.readFileSync(css).toString().replace(cssRE, (match, selector, rule) => {
			return selector.replace(trailingWhitespaceRE, "") + "." + scope;
		});
	} else {
		view = Moon.compile(contents);
	}

	js += `export default Moon.extend("${name}",function(){var options=${data}options.view=function(m,instance,locals){${view}};return options;});`;

	return {
		js: js,
		css: css,
		deps: deps
	};
};
<|endoftext|>


<commit_before>module.exports = {
  'extends': [
    'eslint-config-airbnb/base',
    'eslint-config-airbnb/rules/react',
  ].map(require.resolve),
  rules: {}
};
<commit_msg>Preserve strict rule for default export<commit_after>module.exports = {
  'extends': [
    'eslint-config-airbnb/base',
    'eslint-config-airbnb/rules/strict',
    'eslint-config-airbnb/rules/react',
  ].map(require.resolve),
  rules: {}
};
<|endoftext|>


<commit_before>let readPkgUp = require('read-pkg-up')

let createReporter = require('./create-reporter')
let createHelp = require('./create-help')

function list (obj) {
  return typeof obj === 'object' ? Object.keys(obj) : []
}

console.log(require('@size-limit/webpack'))

function loadModules (pkg) {
  if (!pkg || !pkg.package) return []
  return list(pkg.package.dependencies)
    .concat(list(pkg.package.devDependencies))
    .filter(i => i.startsWith('@size-limit/'))
    .reduce((modules, i) => modules.concat(require(i)), [])
}

function parseArgs () {
  // TODO
  return { }
}

async function findConfig () {
  // TODO
}

async function calc () {
  // TODO
}

module.exports = async process => {
  function hasArg (arg) {
    return process.argv.some(i => i === arg)
  }
  let reporter = createReporter(process, hasArg('--json'))
  let help = createHelp(process)

  try {
    if (hasArg('--version')) {
      return help.showVersion()
    }

    let pkg = await readPkgUp({ cwd: process.cwd() })
    let modules = loadModules(pkg)

    if (hasArg('--help')) {
      return help.showHelp(modules)
    }

    if (!pkg || !pkg.package) {
      throw help.errors.noPackage()
    }

    if (modules.length === 0) {
      help.showMigrationGuide(process)
      return process.exit(1)
    }

    let args = parseArgs(modules, process.argv)
    let config = await findConfig(args, pkg.path)

    let results = await calc(modules, config)
    reporter.results(results)
  } catch (e) {
    reporter.error(e)
    process.exit(1)
  }
}
<commit_msg>More debug<commit_after>let readPkgUp = require('read-pkg-up')

let createReporter = require('./create-reporter')
let createHelp = require('./create-help')

function list (obj) {
  return typeof obj === 'object' ? Object.keys(obj) : []
}

function loadModules (pkg) {
  if (!pkg || !pkg.package) return []
  console.log(
    pkg,
    list(pkg.package.dependencies)
      .concat(list(pkg.package.devDependencies))
      .filter(i => i.startsWith('@size-limit/')),
    list(pkg.package.dependencies)
      .concat(list(pkg.package.devDependencies))
      .filter(i => i.startsWith('@size-limit/'))
      .map(i => require(i))
  )
  return list(pkg.package.dependencies)
    .concat(list(pkg.package.devDependencies))
    .filter(i => i.startsWith('@size-limit/'))
    .reduce((modules, i) => modules.concat(require(i)), [])
}

function parseArgs () {
  // TODO
  return { }
}

async function findConfig () {
  // TODO
}

async function calc () {
  // TODO
}

module.exports = async process => {
  function hasArg (arg) {
    return process.argv.some(i => i === arg)
  }
  let reporter = createReporter(process, hasArg('--json'))
  let help = createHelp(process)

  try {
    if (hasArg('--version')) {
      return help.showVersion()
    }

    let pkg = await readPkgUp({ cwd: process.cwd() })
    let modules = loadModules(pkg)

    if (hasArg('--help')) {
      return help.showHelp(modules)
    }

    if (!pkg || !pkg.package) {
      throw help.errors.noPackage()
    }

    if (modules.length === 0) {
      help.showMigrationGuide(process)
      return process.exit(1)
    }

    let args = parseArgs(modules, process.argv)
    let config = await findConfig(args, pkg.path)

    let results = await calc(modules, config)
    reporter.results(results)
  } catch (e) {
    reporter.error(e)
    process.exit(1)
  }
}
<|endoftext|>