<commit_before>'use strict';

var archiver = require('archiver'),
    fs = require('fs'),
    path = require('path'),
    rimraf = require('rimraf'),
    wrench = require('wrench'),
    azure = require('azure-storage'),
    Q = require('q'),
    manifoldJsLib = require('manifoldjs-lib');

var utils = manifoldJsLib.utils;

function Storage(blobService){
    this.blobService = blobService;
}

Storage.prototype.createZip = function(output, manifest){
    return Q.Promise(function(resolve,reject){
        console.log('Creating zip archive...');
        var archive = archiver('zip'),

        zip = fs.createWriteStream(path.join(output,manifest.content.short_name+'.zip'));

        zip.on('close',function(){
            console.log(archive.pointer() + ' total bytes');
            console.log('archiver has been finalized and the output file descriptor has closed.');

            resolve();
        });

        archive.on('error',function(err){
            reject(err);
        });

        archive.pipe(zip);

        var folderName = path.join(output, utils.sanitizeName(manifest.content.short_name));
        archive.directory(folderName, 'projects', { mode: '0755' }).finalize();
    });
};

Storage.prototype.createContainer = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        console.log('Creating storage container...');
        self.blobService.createContainerIfNotExists(manifest.id, {publicAccessLevel: 'blob'}, function(err) {
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.uploadZip = function(manifest, outputDir, suffix){
    var extension = '.zip';
    return this.uploadFile(manifest, path.join(outputDir,manifest.content.short_name + extension), extension, "-" + suffix);
};

Storage.prototype.uploadFile = function(manifest, filePath, extension, suffix){
    var self = this,
        suffix = suffix || '',
        contentType = (extension == ".zip") ? 'application/zip' : 'application/octet-stream';

    return Q.Promise(function(resolve,reject){
        console.log('Uploading ' + extension + '...');
        self.blobService.createBlockBlobFromLocalFile(manifest.id, manifest.content.short_name + suffix + extension, filePath, { contentType: contentType }, function(err){
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.setPermissions = function(outputDir){
    console.log('Setting permissions on',outputDir,'...');
    wrench.chmodSyncRecursive(outputDir, '0755');
};

Storage.prototype.removeDir = function(outputDir){
    console.log('Deleting output directory...');

    return Q.Promise(function(resolve,reject){
        rimraf(outputDir,{ maxBusyTries: 20 },function(err){
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.getUrlForFile = function(manifest, extension, suffix){
    var container = manifest.id,
    suffix = suffix || '',
    blob = manifest.content.short_name + suffix + extension;

    var startDate = new Date();
    startDate.setMinutes(startDate.getMinutes() - 15);

    var accessPolicy = {
        AccessPolicy: {
            Permissions: azure.BlobUtilities.SharedAccessPermissions.READ,
            Start: startDate,
            Expiry: azure.date.daysFromNow(7)
        }
    };

    var sasToken = this.blobService.generateSharedAccessSignature(container, blob, accessPolicy);
    return this.blobService.getUrl(container,blob,sasToken,true);
};

Storage.prototype.getUrlForZip = function(manifest, suffix){
   return this.getUrlForFile(manifest, '.zip', "-" + suffix);
};

exports.create = function(blobService){
    return new Storage(blobService);
};
<commit_msg>Specified contentDisposition header when generating the package blob's Shared Access Signature. This fixes the issue in Edge and IE that was causing to download the windows 10 package as .zip instead of .web<commit_after>'use strict';

var archiver = require('archiver'),
    fs = require('fs'),
    path = require('path'),
    rimraf = require('rimraf'),
    wrench = require('wrench'),
    azure = require('azure-storage'),
    Q = require('q'),
    manifoldJsLib = require('manifoldjs-lib');

var utils = manifoldJsLib.utils;

function Storage(blobService){
    this.blobService = blobService;
}

Storage.prototype.createZip = function(output, manifest){
    return Q.Promise(function(resolve,reject){
        console.log('Creating zip archive...');
        var archive = archiver('zip'),

        zip = fs.createWriteStream(path.join(output,manifest.content.short_name+'.zip'));

        zip.on('close',function(){
            console.log(archive.pointer() + ' total bytes');
            console.log('archiver has been finalized and the output file descriptor has closed.');

            resolve();
        });

        archive.on('error',function(err){
            reject(err);
        });

        archive.pipe(zip);

        var folderName = path.join(output, utils.sanitizeName(manifest.content.short_name));
        archive.directory(folderName, 'projects', { mode: '0755' }).finalize();
    });
};

Storage.prototype.createContainer = function(manifest){
    var self = this;

    return Q.Promise(function(resolve,reject){
        console.log('Creating storage container...');
        self.blobService.createContainerIfNotExists(manifest.id, {publicAccessLevel: 'blob'}, function(err) {
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.uploadZip = function(manifest, outputDir, suffix){
    var extension = '.zip';
    return this.uploadFile(manifest, path.join(outputDir,manifest.content.short_name + extension), extension, "-" + suffix);
};

Storage.prototype.uploadFile = function(manifest, filePath, extension, suffix){
    var self = this,
        suffix = suffix || '',
        contentType = (extension == ".zip") ? 'application/zip' : 'application/octet-stream';

    return Q.Promise(function(resolve,reject){
        console.log('Uploading ' + extension + '...');
        self.blobService.createBlockBlobFromLocalFile(manifest.id, manifest.content.short_name + suffix + extension, filePath, { contentType: contentType }, function(err){
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.setPermissions = function(outputDir){
    console.log('Setting permissions on',outputDir,'...');
    wrench.chmodSyncRecursive(outputDir, '0755');
};

Storage.prototype.removeDir = function(outputDir){
    console.log('Deleting output directory...');

    return Q.Promise(function(resolve,reject){
        rimraf(outputDir,{ maxBusyTries: 20 },function(err){
            if(err){ return reject(err); }
            return resolve();
        });
    });
};

Storage.prototype.getUrlForFile = function(manifest, extension, suffix){
    var container = manifest.id,
    suffix = suffix || '',
    blob = manifest.content.short_name + suffix + extension;

    var startDate = new Date();
    startDate.setMinutes(startDate.getMinutes() - 15);

    var accessPolicy = {
        AccessPolicy: {
            Permissions: azure.BlobUtilities.SharedAccessPermissions.READ,
            Start: startDate,
            Expiry: azure.date.daysFromNow(7)
        }
    };

    var headers = {
        contentDisposition: 'attachment; filename=' + blob
    };

    var sasToken = this.blobService.generateSharedAccessSignature(container, blob, accessPolicy, headers);
    return this.blobService.getUrl(container,blob,sasToken,true);
};

Storage.prototype.getUrlForZip = function(manifest, suffix){
   return this.getUrlForFile(manifest, '.zip', "-" + suffix);
};

exports.create = function(blobService){
    return new Storage(blobService);
};
<|endoftext|>


<commit_before>
// https://github.com/fullcalendar/fullcalendar/issues/4585
// more related to the 'more+' link than to async event sources
it('rerendering works with async sources and eventLimit', function(done) {
  let cnt = 0

  initCalendar({
    defaultView: 'dayGridMonth',
    eventLimit: 2,
    header: {
      left: 'prev,next today',
      center: 'title',
      right: 'timeGridWeek,dayGridMonth'
    },
    eventSources: [
      getEvents,
      getEvents
    ],
    _eventsPositioned() { // why can't use spyOnCalendarCallback :(
      cnt++
      if (cnt === 1) {
        currentCalendar.next()
        setTimeout(done, 1) // after the async fetch
      }
    }
  })
})

function getEvents(fetchInfo, success) {
  let date = fetchInfo.start
  let events = []

  while (date.getTime() < fetchInfo.end.getTime()) {
    events.push({
      title: 'Event ' + date.getDate(),
      start: date,
      end: new Date(date.getTime() + 1000 * 60 * 60 * 60),
      allDay: false
    })

    date = new Date(date.getTime() + 1000 * 60 * 60 * 24)
  }

  setTimeout(function() {
    success(events)
  }, 0)
}
<commit_msg>change structure of test<commit_after>
// https://github.com/fullcalendar/fullcalendar/issues/4585
// more related to the 'more+' link than to async event sources
describe('async event source rendering with eventLimit', function() {

  it('works', function(done) {
    let cnt = 0

    initCalendar({
      defaultView: 'dayGridMonth',
      eventLimit: 2,
      header: {
        left: 'prev,next today',
        center: 'title',
        right: 'timeGridWeek,dayGridMonth'
      },
      eventSources: [
        getEvents,
        getEvents
      ],
      _eventsPositioned() { // why can't use spyOnCalendarCallback :(
        cnt++
        if (cnt === 1) {
          currentCalendar.next()
          setTimeout(done, 1) // after the async fetch
        }
      }
    })
  })

  function getEvents(fetchInfo, success) {
    let date = fetchInfo.start
    let events = []

    while (date.getTime() < fetchInfo.end.getTime()) {
      events.push({
        title: 'Event ' + date.getDate(),
        start: date,
        end: new Date(date.getTime() + 1000 * 60 * 60 * 60),
        allDay: false
      })

      date = new Date(date.getTime() + 1000 * 60 * 60 * 24)
    }

    setTimeout(function() {
      success(events)
    }, 0)
  }

})
<|endoftext|>


<commit_before>var registerShader = require('../core/shader').registerShader;
var THREE = require('../lib/three');
var utils = require('../utils/');

var CubeLoader = new THREE.CubeTextureLoader();
var texturePromises = {};

/**
 * Standard (physically-based) shader using THREE.MeshStandardMaterial.
 */
module.exports.Shader = registerShader('standard', {
  schema: {
    ambientOcclusionMap: {type: 'map'},
    ambientOcclusionMapIntensity: {default: 1},
    ambientOcclusionTextureOffset: {type: 'vec2'},
    ambientOcclusionTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    color: {type: 'color'},

    displacementMap: {type: 'map'},
    displacementScale: {default: 1},
    displacementBias: {default: 0.5},
    displacementTextureOffset: {type: 'vec2'},
    displacementTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},
    emissive: {type: 'color', default: '#000'},
    emissiveIntensity: {default: 1},
    envMap: {default: ''},

    fog: {default: true},
    height: {default: 256},
    metalness: {default: 0.0, min: 0.0, max: 1.0},

    normalMap: {type: 'map'},
    normalScale: {type: 'vec2', default: {x: 1, y: 1}},
    normalTextureOffset: {type: 'vec2'},
    normalTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    offset: {type: 'vec2', default: {x: 0, y: 0}},
    repeat: {type: 'vec2', default: {x: 1, y: 1}},
    roughness: {default: 0.5, min: 0.0, max: 1.0},
    sphericalEnvMap: {type: 'map'},
    src: {type: 'map'},
    width: {default: 512},
    wireframe: {default: false},
    wireframeLinewidth: {default: 2}
  },

  /**
   * Initializes the shader.
   * Adds a reference from the scene to this entity as the camera.
   */
  init: function (data) {
    this.material = new THREE.MeshStandardMaterial(getMaterialData(data));
    utils.material.updateMap(this, data);
    if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); }
    if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); }
    if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); }
    this.updateEnvMap(data);
  },

  update: function (data) {
    this.updateMaterial(data);
    utils.material.updateMap(this, data);
    if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); }
    if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); }
    if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); }
    this.updateEnvMap(data);
  },

  /**
   * Updating existing material.
   *
   * @param {object} data - Material component data.
   * @returns {object} Material.
   */
  updateMaterial: function (data) {
    var material = this.material;
    data = getMaterialData(data);
    Object.keys(data).forEach(function (key) {
      material[key] = data[key];
    });
  },

  /**
   * Handle environment cubemap. Textures are cached in texturePromises.
   */
  updateEnvMap: function (data) {
    var self = this;
    var material = this.material;
    var envMap = data.envMap;
    var sphericalEnvMap = data.sphericalEnvMap;

    // No envMap defined or already loading.
    if ((!envMap && !sphericalEnvMap) || this.isLoadingEnvMap) {
      material.envMap = null;
      material.needsUpdate = true;
      return;
    }
    this.isLoadingEnvMap = true;

    // if a spherical env map is defined then use it.
    if (sphericalEnvMap) {
      this.el.sceneEl.systems.material.loadTexture(sphericalEnvMap, {src: sphericalEnvMap}, function textureLoaded (texture) {
        self.isLoadingEnvMap = false;
        texture.mapping = THREE.SphericalReflectionMapping;
        material.envMap = texture;
        utils.material.handleTextureEvents(self.el, texture);
        material.needsUpdate = true;
      });
      return;
    }

    // Another material is already loading this texture. Wait on promise.
    if (texturePromises[envMap]) {
      texturePromises[envMap].then(function (cube) {
        self.isLoadingEnvMap = false;
        material.envMap = cube;
        utils.material.handleTextureEvents(self.el, cube);
        material.needsUpdate = true;
      });
      return;
    }

    // Material is first to load this texture. Load and resolve texture.
    texturePromises[envMap] = new Promise(function (resolve) {
      utils.srcLoader.validateCubemapSrc(envMap, function loadEnvMap (urls) {
        CubeLoader.load(urls, function (cube) {
          // Texture loaded.
          self.isLoadingEnvMap = false;
          material.envMap = cube;
          utils.material.handleTextureEvents(self.el, cube);
          resolve(cube);
        });
      });
    });
  }
});

/**
 * Builds and normalize material data, normalizing stuff along the way.
 *
 * @param {object} data - Material data.
 * @returns {object} data - Processed material data.
 */
function getMaterialData (data) {
  var newData = {
    color: new THREE.Color(data.color),
    emissive: new THREE.Color(data.emissive),
    emissiveIntensity: data.emissiveIntensity,
    fog: data.fog,
    metalness: data.metalness,
    roughness: data.roughness,
    wireframe: data.wireframe,
    wireframeLinewidth: data.wireframeLinewidth
  };

  if (data.normalMap) { newData.normalScale = data.normalScale; }

  if (data.ambientOcclusionMap) { newData.aoMapIntensity = data.ambientOcclusionMapIntensity; }

  if (data.displacementMap) {
    newData.displacementScale = data.displacementScale;
    newData.displacementBias = data.displacementBias;
  }

  return newData;
}
<commit_msg>[material] Add metalnessMap and roughnessMap. (#2722)<commit_after>var registerShader = require('../core/shader').registerShader;
var THREE = require('../lib/three');
var utils = require('../utils/');

var CubeLoader = new THREE.CubeTextureLoader();
var texturePromises = {};

/**
 * Standard (physically-based) shader using THREE.MeshStandardMaterial.
 */
module.exports.Shader = registerShader('standard', {
  schema: {
    ambientOcclusionMap: {type: 'map'},
    ambientOcclusionMapIntensity: {default: 1},
    ambientOcclusionTextureOffset: {type: 'vec2'},
    ambientOcclusionTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    color: {type: 'color'},

    displacementMap: {type: 'map'},
    displacementScale: {default: 1},
    displacementBias: {default: 0.5},
    displacementTextureOffset: {type: 'vec2'},
    displacementTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},
    emissive: {type: 'color', default: '#000'},
    emissiveIntensity: {default: 1},
    envMap: {default: ''},

    fog: {default: true},
    height: {default: 256},

    metalness: {default: 0.0, min: 0.0, max: 1.0},
    metalnessMap: {type: 'map'},
    metalnessTextureOffset: {type: 'vec2'},
    metalnessTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    normalMap: {type: 'map'},
    normalScale: {type: 'vec2', default: {x: 1, y: 1}},
    normalTextureOffset: {type: 'vec2'},
    normalTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    offset: {type: 'vec2', default: {x: 0, y: 0}},
    repeat: {type: 'vec2', default: {x: 1, y: 1}},

    roughness: {default: 0.5, min: 0.0, max: 1.0},
    roughnessMap: {type: 'map'},
    roughnessTextureOffset: {type: 'vec2'},
    roughnessTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}},

    sphericalEnvMap: {type: 'map'},
    src: {type: 'map'},
    width: {default: 512},
    wireframe: {default: false},
    wireframeLinewidth: {default: 2}
  },

  /**
   * Initializes the shader.
   * Adds a reference from the scene to this entity as the camera.
   */
  init: function (data) {
    this.material = new THREE.MeshStandardMaterial(getMaterialData(data));
    utils.material.updateMap(this, data);
    if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); }
    if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); }
    if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); }
    if (data.metalnessMap) { utils.material.updateDistortionMap('metalness', this, data); }
    if (data.roughnessMap) { utils.material.updateDistortionMap('roughness', this, data); }
    this.updateEnvMap(data);
  },

  update: function (data) {
    this.updateMaterial(data);
    utils.material.updateMap(this, data);
    if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); }
    if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); }
    if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); }
    if (data.metalnessMap) { utils.material.updateDistortionMap('metalness', this, data); }
    if (data.roughnessMap) { utils.material.updateDistortionMap('roughness', this, data); }
    this.updateEnvMap(data);
  },

  /**
   * Updating existing material.
   *
   * @param {object} data - Material component data.
   * @returns {object} Material.
   */
  updateMaterial: function (data) {
    var material = this.material;
    data = getMaterialData(data);
    Object.keys(data).forEach(function (key) {
      material[key] = data[key];
    });
  },

  /**
   * Handle environment cubemap. Textures are cached in texturePromises.
   */
  updateEnvMap: function (data) {
    var self = this;
    var material = this.material;
    var envMap = data.envMap;
    var sphericalEnvMap = data.sphericalEnvMap;

    // No envMap defined or already loading.
    if ((!envMap && !sphericalEnvMap) || this.isLoadingEnvMap) {
      material.envMap = null;
      material.needsUpdate = true;
      return;
    }
    this.isLoadingEnvMap = true;

    // if a spherical env map is defined then use it.
    if (sphericalEnvMap) {
      this.el.sceneEl.systems.material.loadTexture(sphericalEnvMap, {src: sphericalEnvMap}, function textureLoaded (texture) {
        self.isLoadingEnvMap = false;
        texture.mapping = THREE.SphericalReflectionMapping;
        material.envMap = texture;
        utils.material.handleTextureEvents(self.el, texture);
        material.needsUpdate = true;
      });
      return;
    }

    // Another material is already loading this texture. Wait on promise.
    if (texturePromises[envMap]) {
      texturePromises[envMap].then(function (cube) {
        self.isLoadingEnvMap = false;
        material.envMap = cube;
        utils.material.handleTextureEvents(self.el, cube);
        material.needsUpdate = true;
      });
      return;
    }

    // Material is first to load this texture. Load and resolve texture.
    texturePromises[envMap] = new Promise(function (resolve) {
      utils.srcLoader.validateCubemapSrc(envMap, function loadEnvMap (urls) {
        CubeLoader.load(urls, function (cube) {
          // Texture loaded.
          self.isLoadingEnvMap = false;
          material.envMap = cube;
          utils.material.handleTextureEvents(self.el, cube);
          resolve(cube);
        });
      });
    });
  }
});

/**
 * Builds and normalize material data, normalizing stuff along the way.
 *
 * @param {object} data - Material data.
 * @returns {object} data - Processed material data.
 */
function getMaterialData (data) {
  var newData = {
    color: new THREE.Color(data.color),
    emissive: new THREE.Color(data.emissive),
    emissiveIntensity: data.emissiveIntensity,
    fog: data.fog,
    metalness: data.metalness,
    roughness: data.roughness,
    wireframe: data.wireframe,
    wireframeLinewidth: data.wireframeLinewidth
  };

  if (data.normalMap) { newData.normalScale = data.normalScale; }

  if (data.ambientOcclusionMap) { newData.aoMapIntensity = data.ambientOcclusionMapIntensity; }

  if (data.displacementMap) {
    newData.displacementScale = data.displacementScale;
    newData.displacementBias = data.displacementBias;
  }

  return newData;
}
<|endoftext|>


<commit_before>import { createStore, applyMiddleware, compose } from 'redux';

import apiClientMiddleware from './apiClientMiddleware';
import reducer from './modules';

function makeStore(apiClient, initialState) {
  let composed;

  if (__DEV__) {
    const createLogger = require('redux-logger');
    const persistState = require('redux-devtools').persistState;

    composed = compose(
      applyMiddleware(...[
        apiClientMiddleware(apiClient)
      ].concat(__CLIENT__ ? createLogger({ collapsed: true }) : [])),
      __CLIENT__ ? persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)) : f => f,
      (__CLIENT__ && window.devToolsExtension) ? window.devToolsExtension() : f => f
    );
  } else {
    composed = compose(
      applyMiddleware(
        apiClientMiddleware(apiClient)
      )
    );
  }

  const store = createStore(reducer, initialState, composed);

  if (__DEV__ && module.hot) {
    module.hot.accept('./modules', () =>
      store.replaceReducer(require('./modules'))
    );
  }

  return store;
}

export default makeStore;
<commit_msg>hot reload reducers path<commit_after>import { createStore, applyMiddleware, compose } from 'redux';

import apiClientMiddleware from './apiClientMiddleware';
import reducer from './modules/index';

function makeStore(apiClient, initialState) {
  let composed;

  if (__DEV__) {
    const createLogger = require('redux-logger');
    const persistState = require('redux-devtools').persistState;

    composed = compose(
      applyMiddleware(...[
        apiClientMiddleware(apiClient)
      ].concat(__CLIENT__ ? createLogger({ collapsed: true }) : [])),
      __CLIENT__ ? persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)) : f => f,
      (__CLIENT__ && window.devToolsExtension) ? window.devToolsExtension() : f => f
    );
  } else {
    composed = compose(
      applyMiddleware(
        apiClientMiddleware(apiClient)
      )
    );
  }

  const store = createStore(reducer, initialState, composed);

  if (__DEV__ && module.hot) {
    module.hot.accept('./modules/index', () =>
      store.replaceReducer(require('./modules/index'))
    );
  }

  return store;
}

export default makeStore;
<|endoftext|>


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

  // bc.vc, shortcut
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^.+(https?:\/\/.+)$/,
    },
    start: function (m) {
      $.openLink(m.path[1] + document.location.search + document.location.hash);
    },
  });

  function decompress (script, unzip) {
    if (!unzip) {
      return script;
    }
    var matches = script.match(/eval(.*)/);
    matches = matches[1];
    script = eval(matches);
    return script;
  }

  function searchScript (unzip) {
    var content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('make_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: false,
        script: decompress(content.payload, unzip),
      };
    }
    content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('click_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: true,
        script: decompress(content.payload, unzip),
      };
    }
    throw _.AdsBypasserError('script changed');
  }

  function knockServer (script, dirtyFix) {
    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    var i = setInterval(function () {
      $.post(make_url, make_opts, function (text) {
        if (dirtyFix) {
          // dirty fix for tr5.in
          text = text.match(/\{.+\}/)[0];
        }
        var jj = JSON.parse(text);
        if (jj.message) {
          clearInterval(i);
          $.openLink(jj.message.url);
        }
      });
    }, 1000);
  }

  function knockServer2 (script) {
    // somehow I must use jQuery AJAX
    var post = unsafeWindow.$.post;
    // mock a fake AJAX function
    unsafeWindow.$.post = $.inject(function (a, b, c) {
      if (typeof c !== 'function') {
        return;
      }
      setTimeout(function () {
        var data = {
          error: false,
          message: {
            url: '#',
          },
        };
        c(JSON.stringify(data));
      }, 1000);
    });

    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    function makeLog () {
        make_opts.opt = 'make_log';
        post(make_url, $.inject(make_opts), $.inject(function (text) {
          var data = JSON.parse(text);
          _.info('make_log', data);
          if (!data.message) {
            checksLog();
            return;
          }

          $.openLink(data.message.url);
        }));
    }

    function checkLog () {
      make_opts.opt = 'check_log';
      post(make_url, $.inject(make_opts), $.inject(function (text) {
        var data = JSON.parse(text);
        _.info('check_log', data);
        if (!data.message) {
          checkLog();
          return;
        }

        makeLog();
      }));
    }

    function checksLog () {
      make_opts.opt = 'checks_log';
      post(make_url, $.inject(make_opts), $.inject(function () {
        _.info('checks_log');
        checkLog();
      }));
    }

    checksLog();
  }

  // bc.vc
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var result = searchScript(false);
      if (!result.direct) {
        knockServer2(result.script);
      } else {
        result = result.script.match(/top\.location\.href = '([^']+)'/);
        if (!result) {
          throw new _.AdsBypasserError('script changed');
        }
        result = result[1];
        $.openLink(result);
      }
    },
  });

  function run (dirtyFix) {
    // prevent redirection by iframe
    $.removeNodes('iframe');

    var result = searchScript(true);
    if (!result.direct) {
      knockServer(result.script,dirtyFix);
    } else {
      result = result.script.match(/top\.location\.href='([^']+)'/);
      if (!result) {
        throw new _.AdsBypasserError('script changed');
      }
      result = result[1];
      $.openLink(result);
    }
  }

  // adcrun.ch
  $.register({
    rule: {
      host: /^adcrun\.ch$/,
      path: /^\/\w+$/,
    },
    ready: function () {
      // Try to bypass the survey
      $.removeNodes('.user_content');

      var rSurveyLink = /http\.open\("GET", "api_ajax\.php\?sid=\d*&ip=[^&]*&longurl=([^"]+)" \+ first_time, (?:true|false)\);/;
      var l = $.searchScripts(rSurveyLink);
      // Redirect to the target link if we found it
      if (l) {
        $.openLink(l[1]);
        return;
      }

      // Otherwise it's most likely a simple bc.vc-like link
      // Malformed JSON
      run(true);
    },
  });

  $.register({
    rule: {
      host: [
        /^1tk\.us$/,
        /^gx\.si$/,
        /^adwat\.ch$/,
        /^(fly2url|urlwiz|xafox)\.com$/,
        /^(zpoz|ultry)\.net$/,
        /^(wwy|myam)\.me$/,
        /^ssl\.gs$/,
        /^link\.tl$/,
        /^hit\.us$/,
        /^shortit\.in$/,
        /^(adbla|tl7)\.us$/,
        /^www\.adjet\.eu$/,
        /^srk\.gs$/,
        /^cun\.bz$/,
        /^miniurl\.tk$/,
      ],
      path: /^\/.+/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^adtr\.im|ysear\.ch|xip\.ir$/,
      path: /^\/.+/,
    },
    ready: function () {
      var a = $.$('div.fly_head a.close');
      var f = $.$('iframe.fly_frame');
      // the iframe may be an ad link
      // so also check the close button
      if (a && f) {
        $.openLink(f.src);
      } else {
        run();
      }
    },
  });

  $.register({
    rule: {
      host: /^ad5\.eu$/,
      path: /^\/[^.]+$/,
    },
    ready: function() {
      $.removeNodes('iframe');
      var s = searchScript(true);

      // Find the form
      var m = s.script.match(/(<form name="form1"method="post".*(?!<\\form>)<\/form>)/);

      if (!m) {return;}

      m = m[1];

      // Set the correct timezone
      var tz = -(new Date().getTimezoneOffset()/60);
      m = m.replace("'+timezone+'",tz);

      // Wrap the form into a useless div
      var d = document.createElement('div');
      d.setAttribute('id','AdsBypasserFTW');
      d.setAttribute('style', 'display:none;');

      // Feed with the right form
      d.innerHTML = m;
      document.body.appendChild(d);

      // Redirect to next page
      $('#AdsBypasserFTW > form[name=form1]').submit();
    },
  });

  $.register({
    rule: {
      host: /^tr5\.in$/,
      path: /^\/.+/,
    },
    ready: function () {
      // Malformed JSON
      run(true);
    },
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>Support for vizzy.es<commit_after>(function () {
  'use strict';

  // bc.vc, shortcut
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^.+(https?:\/\/.+)$/,
    },
    start: function (m) {
      $.openLink(m.path[1] + document.location.search + document.location.hash);
    },
  });

  function decompress (script, unzip) {
    if (!unzip) {
      return script;
    }
    var matches = script.match(/eval(.*)/);
    matches = matches[1];
    script = eval(matches);
    return script;
  }

  function searchScript (unzip) {
    var content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('make_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: false,
        script: decompress(content.payload, unzip),
      };
    }
    content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('click_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: true,
        script: decompress(content.payload, unzip),
      };
    }
    throw _.AdsBypasserError('script changed');
  }

  function knockServer (script, dirtyFix) {
    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    var i = setInterval(function () {
      $.post(make_url, make_opts, function (text) {
        if (dirtyFix) {
          // dirty fix for tr5.in
          text = text.match(/\{.+\}/)[0];
        }
        var jj = JSON.parse(text);
        if (jj.message) {
          clearInterval(i);
          $.openLink(jj.message.url);
        }
      });
    }, 1000);
  }

  function knockServer2 (script) {
    // somehow I must use jQuery AJAX
    var post = unsafeWindow.$.post;
    // mock a fake AJAX function
    unsafeWindow.$.post = $.inject(function (a, b, c) {
      if (typeof c !== 'function') {
        return;
      }
      setTimeout(function () {
        var data = {
          error: false,
          message: {
            url: '#',
          },
        };
        c(JSON.stringify(data));
      }, 1000);
    });

    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    function makeLog () {
        make_opts.opt = 'make_log';
        post(make_url, $.inject(make_opts), $.inject(function (text) {
          var data = JSON.parse(text);
          _.info('make_log', data);
          if (!data.message) {
            checksLog();
            return;
          }

          $.openLink(data.message.url);
        }));
    }

    function checkLog () {
      make_opts.opt = 'check_log';
      post(make_url, $.inject(make_opts), $.inject(function (text) {
        var data = JSON.parse(text);
        _.info('check_log', data);
        if (!data.message) {
          checkLog();
          return;
        }

        makeLog();
      }));
    }

    function checksLog () {
      make_opts.opt = 'checks_log';
      post(make_url, $.inject(make_opts), $.inject(function () {
        _.info('checks_log');
        checkLog();
      }));
    }

    checksLog();
  }

  // bc.vc
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var result = searchScript(false);
      if (!result.direct) {
        knockServer2(result.script);
      } else {
        result = result.script.match(/top\.location\.href = '([^']+)'/);
        if (!result) {
          throw new _.AdsBypasserError('script changed');
        }
        result = result[1];
        $.openLink(result);
      }
    },
  });

  function run (dirtyFix) {
    // prevent redirection by iframe
    $.removeNodes('iframe');

    var result = searchScript(true);
    if (!result.direct) {
      knockServer(result.script,dirtyFix);
    } else {
      result = result.script.match(/top\.location\.href='([^']+)'/);
      if (!result) {
        throw new _.AdsBypasserError('script changed');
      }
      result = result[1];
      $.openLink(result);
    }
  }

  // adcrun.ch
  $.register({
    rule: {
      host: /^adcrun\.ch$/,
      path: /^\/\w+$/,
    },
    ready: function () {
      // Try to bypass the survey
      $.removeNodes('.user_content');

      var rSurveyLink = /http\.open\("GET", "api_ajax\.php\?sid=\d*&ip=[^&]*&longurl=([^"]+)" \+ first_time, (?:true|false)\);/;
      var l = $.searchScripts(rSurveyLink);
      // Redirect to the target link if we found it
      if (l) {
        $.openLink(l[1]);
        return;
      }

      // Otherwise it's most likely a simple bc.vc-like link
      // Malformed JSON
      run(true);
    },
  });

  $.register({
    rule: {
      host: [
        /^1tk\.us$/,
        /^gx\.si$/,
        /^adwat\.ch$/,
        /^(fly2url|urlwiz|xafox)\.com$/,
        /^(zpoz|ultry)\.net$/,
        /^(wwy|myam)\.me$/,
        /^ssl\.gs$/,
        /^link\.tl$/,
        /^hit\.us$/,
        /^shortit\.in$/,
        /^(adbla|tl7)\.us$/,
        /^www\.adjet\.eu$/,
        /^srk\.gs$/,
        /^cun\.bz$/,
        /^miniurl\.tk$/,
        /^vizzy\.es$/,
      ],
      path: /^\/.+/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^adtr\.im|ysear\.ch|xip\.ir$/,
      path: /^\/.+/,
    },
    ready: function () {
      var a = $.$('div.fly_head a.close');
      var f = $.$('iframe.fly_frame');
      // the iframe may be an ad link
      // so also check the close button
      if (a && f) {
        $.openLink(f.src);
      } else {
        run();
      }
    },
  });

  $.register({
    rule: {
      host: /^ad5\.eu$/,
      path: /^\/[^.]+$/,
    },
    ready: function() {
      $.removeNodes('iframe');
      var s = searchScript(true);

      // Find the form
      var m = s.script.match(/(<form name="form1"method="post".*(?!<\\form>)<\/form>)/);

      if (!m) {return;}

      m = m[1];

      // Set the correct timezone
      var tz = -(new Date().getTimezoneOffset()/60);
      m = m.replace("'+timezone+'",tz);

      // Wrap the form into a useless div
      var d = document.createElement('div');
      d.setAttribute('id','AdsBypasserFTW');
      d.setAttribute('style', 'display:none;');

      // Feed with the right form
      d.innerHTML = m;
      document.body.appendChild(d);

      // Redirect to next page
      $('#AdsBypasserFTW > form[name=form1]').submit();
    },
  });

  $.register({
    rule: {
      host: /^tr5\.in$/,
      path: /^\/.+/,
    },
    ready: function () {
      // Malformed JSON
      run(true);
    },
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>const showChart      = require('./charts/webtrader_chart').showChart;
const Defaults       = require('./defaults');
const getActiveTab   = require('./get_active_tab').getActiveTab;
const GetTicks       = require('./get_ticks');
const MBDefaults     = require('../mb_trade/mb_defaults');
const getLanguage    = require('../../base/language').get;
const State          = require('../../base/storage').State;
const Url            = require('../../base/url');
const JapanPortfolio = require('../../../binary_japan/trade_japan/portfolio');

/*
 * This file contains the code related to loading of trading page bottom analysis
 * content. It will contain jquery so as to compatible with old code and less rewrite
 *
 * Please note that this will be removed in near future
 */

/*
 * This function is called whenever we change market, form
 * or underlying to load bet analysis for that particular event
 */

const TradingAnalysis = (() => {
    const hidden_class = 'invisible';
    let form_name;

    const requestTradeAnalysis = () => {
        form_name = (State.get('is_mb_trading') ? MBDefaults.get('category') : Defaults.get('formname')) || 'risefall';

        const map_obj = { matchdiff: 'digits', callput: 'higherlower' };
        const regex   = new RegExp(Object.keys(map_obj).join('|'), 'gi');
        form_name     = form_name.replace(regex, matched => map_obj[matched]);

        $('#tab_last_digit').setVisibility(/digits|overunder|evenodd/.test(form_name));
        sessionStorage.setItem('currentAnalysisTab', getActiveTab());
        loadAnalysisTab();
    };

    /*
     * This function bind event to link elements of bottom content
     * navigation
     */
    const bindAnalysisTabEvent = () => {
        $('#betsBottomPage').find('li a').on('click', (e) => {
            e.preventDefault();
            const li = e.target.parentElement;
            sessionStorage.setItem('currentAnalysisTab', li.id);
            if (!li.classList.contains('active')) {
                loadAnalysisTab(li.id);
            }
        });
    };

    /*
     * This function handles all the functionality on how to load
     * tab according to current paramerted
     */
    const loadAnalysisTab = (tab) => {
        const current_tab = tab || getActiveTab();
        $('#betsBottomPage').find('li').removeClass('active');
        $(`#${current_tab}`).addClass('active');
        toggleActiveAnalysisTabs();
        JapanPortfolio.init();
        if (State.get('is_mb_trading')) {
            showChart();
        }
        if (current_tab === 'tab_portfolio') {
            JapanPortfolio.show();
        } else {
            JapanPortfolio.hide();
            if (current_tab === 'tab_graph') {
                showChart();
            } else if (current_tab === 'tab_last_digit') {
                const populateDigits = (value) => {
                    const tick = $('#tick_count').val() || 100;
                    GetTicks.request('', {
                        ticks_history: value,
                        count        : tick.toString(),
                        end          : 'latest',
                    });
                };

                const underlying = $('#digit_underlying option:selected').val() || $('#underlying').find('option:selected').val();
                populateDigits(underlying);

                const syncDigits = () => {
                    if(getActiveTab() === 'tab_last_digit' && getActiveTab() !== 'tab_graph' && getActiveTab() !== 'tab_explanation') {
                        if($('#digit_underlying option:selected').val() !== $('#underlying option:selected').val()) {
                            if($('#contract_markets option:selected').val() === 'volidx' || $('#contract_markets option:selected').val() === 'random_index' || $('#contract_markets option:selected').val() === 'random_daily') {
                                const parent_underlying = $('#underlying option:selected').val();
                                populateDigits(parent_underlying);
                                const underlyingText = $('#underlying :selected').text();
                                $('#digit_info_underlying').text(underlyingText);
                                $('#digit_underlying').val(parent_underlying).change();
                            }
                        }
                    }
                };
                $('#contract_markets').off('change').on('change',syncDigits);
                $('#underlying').off('change').on('change',syncDigits);

            } else if (current_tab === 'tab_explanation') {
                showExplanation();
            }
        }
    };

    /*
     * function to toggle the active element for analysis menu
     */
    const toggleActiveAnalysisTabs = () => {
        const current_tab        = getActiveTab();
        const analysis_container = document.getElementById('bet_bottom_content');

        if (analysis_container) {
            const child_elements      = analysis_container.children;
            const current_tab_element = document.getElementById(`${current_tab}-content`);
            const classes             = current_tab_element.classList;

            for (let i = 0, len = child_elements.length; i < len; i++) {
                child_elements[i].classList.remove('selectedTab');
                child_elements[i].classList.add(hidden_class);
            }

            classes.add('selectedTab');
            classes.remove(hidden_class);
        }
    };

    /*
     * handle the display of proper explanation based on parameters
     */
    const showExplanation = () => {
        const $container = $('#tab_explanation-content');

        $container.find('#explanation_winning > div, #explanation_explain > div, #explanation_image').setVisibility(0);
        $container.find(`#explanation_winning, #winning_${form_name}, #explanation_explain, #explain_${form_name}`).setVisibility(1);

        const images = {
            risefall: {
                image1: 'rise-fall-1.svg',
                image2: 'rise-fall-2.svg',
            },
            higherlower: {
                image1: 'higher-lower-1.svg',
                image2: 'higher-lower-2.svg',
            },
            touchnotouch: {
                image1: 'touch-notouch-1.svg',
                image2: 'touch-notouch-2.svg',
            },
            endsinout: {
                image1: 'in-out-1.svg',
                image2: 'in-out-2.svg',
            },
            staysinout: {
                image1: 'in-out-3.svg',
                image2: 'in-out-4.svg',
            },
            updown: {
                image1: 'up-down-1.svg',
                image2: 'up-down-2.svg',
            },
            evenodd: {
                image1: 'evenodd-1.svg',
                image2: 'evenodd-2.svg',
            },
            overunder: {
                image1: 'overunder-1.svg',
                image2: 'overunder-2.svg',
            },
        };

        if (images[form_name]) {
            const image_path = Url.urlForStatic(`images/pages/trade-explanation/${(getLanguage() === 'JA' ? 'ja/' : '')}`);
            $container.find('#explanation_image_1').attr('src', image_path + images[form_name].image1);
            $container.find('#explanation_image_2').attr('src', image_path + images[form_name].image2);
            $container.find('#explanation_image').setVisibility(1);
        }
    };

    return {
        bindAnalysisTabEvent,
        request: requestTradeAnalysis,
    };
})();

module.exports = TradingAnalysis;
<commit_msg>updated synching function in digits_last_tab<commit_after>const showChart      = require('./charts/webtrader_chart').showChart;
const Defaults       = require('./defaults');
const getActiveTab   = require('./get_active_tab').getActiveTab;
const GetTicks       = require('./get_ticks');
const MBDefaults     = require('../mb_trade/mb_defaults');
const getLanguage    = require('../../base/language').get;
const State          = require('../../base/storage').State;
const Url            = require('../../base/url');
const JapanPortfolio = require('../../../binary_japan/trade_japan/portfolio');

/*
 * This file contains the code related to loading of trading page bottom analysis
 * content. It will contain jquery so as to compatible with old code and less rewrite
 *
 * Please note that this will be removed in near future
 */

/*
 * This function is called whenever we change market, form
 * or underlying to load bet analysis for that particular event
 */

const TradingAnalysis = (() => {
    const hidden_class = 'invisible';
    let form_name;

    const requestTradeAnalysis = () => {
        form_name = (State.get('is_mb_trading') ? MBDefaults.get('category') : Defaults.get('formname')) || 'risefall';

        const map_obj = { matchdiff: 'digits', callput: 'higherlower' };
        const regex   = new RegExp(Object.keys(map_obj).join('|'), 'gi');
        form_name     = form_name.replace(regex, matched => map_obj[matched]);

        $('#tab_last_digit').setVisibility(/digits|overunder|evenodd/.test(form_name));
        sessionStorage.setItem('currentAnalysisTab', getActiveTab());
        loadAnalysisTab();
    };

    /*
     * This function bind event to link elements of bottom content
     * navigation
     */
    const bindAnalysisTabEvent = () => {
        $('#betsBottomPage').find('li a').on('click', (e) => {
            e.preventDefault();
            const li = e.target.parentElement;
            sessionStorage.setItem('currentAnalysisTab', li.id);
            if (!li.classList.contains('active')) {
                loadAnalysisTab(li.id);
            }
        });
    };

    /*
     * This function handles all the functionality on how to load
     * tab according to current paramerted
     */
    const loadAnalysisTab = (tab) => {
        const current_tab = tab || getActiveTab();
        $('#betsBottomPage').find('li').removeClass('active');
        $(`#${current_tab}`).addClass('active');
        toggleActiveAnalysisTabs();
        JapanPortfolio.init();
        if (State.get('is_mb_trading')) {
            showChart();
        }
        if (current_tab === 'tab_portfolio') {
            JapanPortfolio.show();
        } else {
            JapanPortfolio.hide();
            if (current_tab === 'tab_graph') {
                showChart();
            } else if (current_tab === 'tab_last_digit') {
                const el_digit_underlying = $('#digit_underlying');
                const underlying = $('#underlying option:selected').val();
                const tick       = $('#tick_count').val() || 100;
                if (underlying !== el_digit_underlying.find('option:selected').val()) {
                    el_digit_underlying.find(`option[value="${underlying}"]`).prop('selected', true).trigger('change');
                    GetTicks.request('', {
                        ticks_history: underlying,
                        count        : tick.toString(),
                        end          : 'latest',
                    });
                }
            } else if (current_tab === 'tab_explanation') {
                showExplanation();
            }
        }
    };

    /*
     * function to toggle the active element for analysis menu
     */
    const toggleActiveAnalysisTabs = () => {
        const current_tab        = getActiveTab();
        const analysis_container = document.getElementById('bet_bottom_content');

        if (analysis_container) {
            const child_elements      = analysis_container.children;
            const current_tab_element = document.getElementById(`${current_tab}-content`);
            const classes             = current_tab_element.classList;

            for (let i = 0, len = child_elements.length; i < len; i++) {
                child_elements[i].classList.remove('selectedTab');
                child_elements[i].classList.add(hidden_class);
            }

            classes.add('selectedTab');
            classes.remove(hidden_class);
        }
    };

    /*
     * handle the display of proper explanation based on parameters
     */
    const showExplanation = () => {
        const $container = $('#tab_explanation-content');

        $container.find('#explanation_winning > div, #explanation_explain > div, #explanation_image').setVisibility(0);
        $container.find(`#explanation_winning, #winning_${form_name}, #explanation_explain, #explain_${form_name}`).setVisibility(1);

        const images = {
            risefall: {
                image1: 'rise-fall-1.svg',
                image2: 'rise-fall-2.svg',
            },
            higherlower: {
                image1: 'higher-lower-1.svg',
                image2: 'higher-lower-2.svg',
            },
            touchnotouch: {
                image1: 'touch-notouch-1.svg',
                image2: 'touch-notouch-2.svg',
            },
            endsinout: {
                image1: 'in-out-1.svg',
                image2: 'in-out-2.svg',
            },
            staysinout: {
                image1: 'in-out-3.svg',
                image2: 'in-out-4.svg',
            },
            updown: {
                image1: 'up-down-1.svg',
                image2: 'up-down-2.svg',
            },
            evenodd: {
                image1: 'evenodd-1.svg',
                image2: 'evenodd-2.svg',
            },
            overunder: {
                image1: 'overunder-1.svg',
                image2: 'overunder-2.svg',
            },
        };

        if (images[form_name]) {
            const image_path = Url.urlForStatic(`images/pages/trade-explanation/${(getLanguage() === 'JA' ? 'ja/' : '')}`);
            $container.find('#explanation_image_1').attr('src', image_path + images[form_name].image1);
            $container.find('#explanation_image_2').attr('src', image_path + images[form_name].image2);
            $container.find('#explanation_image').setVisibility(1);
        }
    };

    return {
        bindAnalysisTabEvent,
        request: requestTradeAnalysis,
    };
})();

module.exports = TradingAnalysis;
<|endoftext|>


<commit_before>// namespace
var App = App || {};

App.MainMenuState = (function () {
    "use strict";

    var fn = function (game) {
        Phaser.State.call(this, game);
    };

    fn.prototype = Object.create(Phaser.State.prototype);
    fn.prototype.constructor = fn;

    fn.prototype.init = function () {
        this.config = this.game.cache.getJSON('mainMenuConfig');

        _.each(this.config.items, (function (item) {
            var text = this.add.text(0, 0, item.label, this.config.style);

            text.setTextBounds(0,0,this.world.width,this.world.height);

            text.inputEnabled = true;

            text.events.onInputUp.add(function (ev) {
                this.state.start('PlayMission');
            }, this);
        }).bind(this));
    };

    return fn;
})();
<commit_msg>Outer space<commit_after>// namespace
var App = App || {};

App.MainMenuState = (function () {
    "use strict";

    var fn = function (game) {
        Phaser.State.call(this, game);
    };

    fn.prototype = Object.create(Phaser.State.prototype);
    fn.prototype.constructor = fn;

    fn.prototype.init = function () {
        this.config = this.game.cache.getJSON('mainMenuConfig');

        _.each(this.config.items, (function (item) {
            var text = this.add.text(0, 0, item.label, this.config.style);

            text.setTextBounds(0,0,this.world.width,this.world.height);

            text.inputEnabled = true;

            text.events.onInputUp.add(function (ev) {
                this.state.start('PlayMission');
            }, this);
        }).bind(this));
    };

    return fn;
})();
<|endoftext|>


<commit_before>export default register

import chalk from 'chalk'
import prompt from 'prompt'
import config from '../config'
import server from '../server'
import { setConfig } from '../config'

function register (yargs) {
  let argv = yargs
  .usage('Usage: tick register')
  .help('h')
  .alias('h', 'help')
  .argv

  let values = [
    { name : 'username' },
    { name : 'password', hidden : true }
  ]

  prompt.message = ''
  prompt.delimiter = ''
  prompt.start()

  prompt.get(values, (err, user) => {
    if (err) throw err
    server.register(user)
    .then(user => setConfig('remote', user.couch.url))
    .then(() => console.log(chalk.bgGreen('Account created')))
    .catch(err => console.error(chalk.bgRed('Error'), err.data))
  })

}
<commit_msg>register with email, show all errors<commit_after>export default register

import chalk from 'chalk'
import prompt from 'prompt'
import config from '../config'
import server from '../server'
import { setConfig } from '../config'

function register (yargs) {
  let argv = yargs
  .usage('Usage: tick register')
  .help('h')
  .alias('h', 'help')
  .argv

  let values = [
    { name : 'username' },
    { name : 'email' },
    { name : 'password', hidden : true }

  ]

  prompt.message = ''
  prompt.delimiter = ''
  prompt.start()

  prompt.get(values, (err, user) => {
    if (err) throw err
    server.register(user)
    .then(user => setConfig('remote', user.couch.url))
    .then(() => console.log(chalk.bgGreen('Account created')))
    .catch(handleError)
  })
}

function handleError (err) {
  let message = err.data
  if (message instanceof Array) {
    message = message.join('\n')
  }
  console.error(chalk.bgRed('Error'), message)
}
<|endoftext|>


<commit_before>import RxReact from 'rx-react';
import React from 'react';
let StateStreamMixin = RxReact.StateStreamMixin;
let FuncSubject      = RxReact.FuncSubject;

import Rx from 'rx'
let Observable= Rx.Observable;
let fromEvent = Observable.fromEvent;

import {formatNumberTo} from '../utils/formatters'

import logger from '../utils/log'
let log = logger("Jam-ToolBar");
log.setLevel("info");

/*
  Component to display (& edit) some of the main properties of entities: ie
  - position
  - rotation
  - scale
*/
class EntityInfos extends RxReact.Component {
  constructor(props) {
    super(props);
    this.state={entityName:""}
    this.keyup = FuncSubject.create();

    this.degreeAngles = true;
    this.meshSize= {w:0,l:0,h:0};
  }
  componentWillReceiveProps(nextProps){
    let entities = nextProps.entities;
    if(entities && entities.length >0 )
    {
      this.setState({
        entityName:entities[0].name
      })
    }
  }

  getStateStream() {
    //return (
    //  Observable.empty());
    function loggg(text){
      console.log("here",text)
      return text
    }
    return (
      this.keyup
      .map((e) => e.target.value)
      .filter(text => text.length > 2)
      //.throttle(750)
      .distinctUntilChanged()
      //.flatMapLatest(text => searchWikipedia(text))
      //.map(loggg)
      .map(results => ({entityName: results}))
    );
  }

  _keyup(event){
    console.log(event)
    this.setState({results: event.target.value});
  }

  handleChange(event) {
    console.log(event)
    this.setState({value: event.target.value});
  }

  handleAngleInput(event){
    let value = event.target.value;
  }

  /*foo() {
    onKeyDown={this.handleKeyDown} onChange={this.handleChange} onBlur={this.handleBlur}
  }*/

  render() {
    //let styles = Object.assign({}, this.constructor.styles);
    let styles ={
      numbers:{
        width:"10em",
        maxWidth: "50px",
        border: "none",
        lineHeight: "0.8em",
        fontSize: "0.8em",
        fontFamily: "inherit",
      },
      text:{
        maxWidth: "150px",
        border: "none",
        lineHeight: "0.8em",
        fontSize: "0.8em",
        fontFamily: "inherit",
      }

    }

    let fieldStyle={
      width:"10em",
      maxWidth: "50px",
      border: "none",
      lineHeight: "0.8em",
      fontSize: "0.8em",
      fontFamily: "inherit",
    }

    /*let entity ={
      name:"foo",
      type:"yeah",
      pos : [10,0,-7],
      rot : [0,0,7],
      scale: [0,0,0]
    }*/
    let entityInfo;
    let canDisplay = this.props.entities.length>0;

    /*var value = this.state.value;
    entityInfo =

      HELLO THERE
       <input type="text" value={value} style={styles.text} onChange={this.handleChange.bind(this)} >  </input>

*/
     let numberPrecision = 2;

    var entityName = this.state && this.state.entityName || [];

    if(canDisplay){
      let entity= this.props.entities[0] ;
      let self  = this;//workaround for babel + jsx "this" issue

      let positionInputs = [];
      entity.pos.forEach(function(entry){
        let entry = formatNumberTo(entry, numberPrecision);
        positionInputs.push(<input type="number" value={entry} style={styles.numbers} />);
      })

      let rotationInputs = [];
      entity.rot.forEach(function(entry){
        let entry = formatNumberTo(entry, numberPrecision);
        rotationInputs.push(<input type="number" value={entry} style={styles.numbers}/>);
      })

      let scaleInputs = [];
      entity.sca.forEach(function(entry){
        let entry = formatNumberTo(entry, numberPrecision);
        scaleInputs.push(<input type="number" value={entry} style={styles.numbers}/>);
      })

      entityInfo = (

            N:
            <input type="text" value={entityName} style={styles.text} onChange={this.keyup.bind(this)}> </input>

            P: {positionInputs}

            R: {rotationInputs}

            S: {scaleInputs}

)
    }

    return (

       {entityInfo}

    );
  }
}

export default EntityInfos<commit_msg>- refined and improved entityInfos component:  * added usage of actions/observable to dispatch/propagate events from the inputs  * a bit clunky but it works!  * restructured & cleaned up code a bit  * added stubs for absolute size display<commit_after>import RxReact from 'rx-react';
import React from 'react';
let StateStreamMixin = RxReact.StateStreamMixin;
let FuncSubject      = RxReact.FuncSubject;

import Rx from 'rx'
let Observable= Rx.Observable;
let fromEvent = Observable.fromEvent;

import {formatNumberTo, toAbsSize} from '../utils/formatters'

import logger from '../utils/log'
let log = logger("Jam-ToolBar");
log.setLevel("info");

import {setEntityTransforms} from '../actions/entityActions'

/*
  Component to display (& edit) some of the main properties of entities: ie
  - position
  - rotation
  - scale
*/
class EntityInfos extends RxReact.Component {
  constructor(props) {
    super(props);
    this.state={entityName:""}
    this.keyup = FuncSubject.create();

    this.degreeAngles = true;
  }

  componentWillReceiveProps(nextProps){
    let entities = nextProps.entities;
    if(entities && entities.length >0 )
    {
      this.setState({
        entityName:entities[0].name
      })
    }
  }

  getStateStream() {
    //return (
    //  Observable.empty());
    function loggg(text){
      console.log("here",text)
      return text
    }
    return (
      this.keyup
      .map((e) => e.target.value)
      .filter(text => text.length > 2)
      //.throttle(750)
      .distinctUntilChanged()
      //.flatMapLatest(text => searchWikipedia(text))
      //.map(loggg)
      .map(results => ({entityName: results}))
    );
  }

  _keyup(event){
    console.log(event)
    this.setState({results: event.target.value});
  }

  handleChange(type, index, event) {
    console.log(type, index, parseFloat(event.target.value));
    //this.setState({value: event.target.value});
    let entity= this.props.entities[0] ;
    let attrs = {
      pos:Object.assign([],entity.pos),
      rot:Object.assign([],entity.rot),
      sca:Object.assign([],entity.sca),
    };
    attrs[type][index]=parseFloat(event.target.value);

    setEntityTransforms(entity,attrs)
  }

  handleAngleInput(event){
    let value = event.target.value;
  }

  render() {
    //let styles = Object.assign({}, this.constructor.styles);
    let styles ={
      numbers:{
        width:"10em",
        maxWidth: "50px",
        border: "none",
        lineHeight: "0.8em",
        fontSize: "0.8em",
        fontFamily: "inherit",
      },
      text:{
        maxWidth: "150px",
        border: "none",
        lineHeight: "0.8em",
        fontSize: "0.8em",
        fontFamily: "inherit",
      }

    }

    let fieldStyle={
      width:"10em",
      maxWidth: "50px",
      border: "none",
      lineHeight: "0.8em",
      fontSize: "0.8em",
      fontFamily: "inherit",
    }

    /*let entity ={
      name:"foo",
      type:"yeah",
      pos : [10,0,-7],
      rot : [0,0,7],
      sca: [0,0,0]
    }*/
    let entityInfo;
    let canDisplay = this.props.entities.length>0;

    let numberPrecision = 2;
    let controlsStep = 0.1;

    var entityName = this.state && this.state.entityName || [];

    if(canDisplay){
      let entity= this.props.entities[0] ;
      //let absSize = toAbsSize(entity.sca)

      let self  = this;//workaround for babel + jsx "this" issue

      let positionInputs = [];
      entity.pos.forEach(function(entry, index){
        let entry = formatNumberTo(entry, numberPrecision);
        positionInputs.push(<input type="number"
          value={entry}
          step= {controlsStep}
          style={styles.numbers}
          onChange={self.handleChange.bind(self,"pos",index)} />);
      })

      let rotationInputs = [];
      entity.rot.forEach(function(entry, index){
        let entry = formatNumberTo(entry, numberPrecision);
        rotationInputs.push(<input type="number"
          value={entry}
          step = {controlsStep}
          style={styles.numbers}
          onChange={self.handleChange.bind(self,"rot",index)} />);
      })

      let scaleInputs = [];
      entity.sca.forEach(function(entry, index){
        let entry = formatNumberTo(entry, numberPrecision);
        scaleInputs.push(
          <input type="number"
          value={entry}
          step={controlsStep}
          style={styles.numbers}
          onChange={self.handleChange.bind(self,"sca",index)} />);
      })

      let absSizeInputs = [];
      console.log("BBOX",entity.bbox)
      entity.sca.forEach(function(entry, index){
        let entry = formatNumberTo(entry, numberPrecision);
        absSizeInputs.push(
          <input type="number"
          value={entry}
          step={controlsStep}
          style={styles.numbers}
          onChange={self.handleChange.bind(self,"sca",index)} />
          );
      })

      entityInfo = (

            N:
            <input type="text" value={entityName} style={styles.text} onChange={this.keyup.bind(this)}> </input>

            P: {positionInputs}

            R: {rotationInputs}

            S: {scaleInputs}

            D: {absSizeInputs}

)
    }

    return (

       {entityInfo}

    );
  }
}

export default EntityInfos<|endoftext|>


<commit_before>import React from 'react';
import CommentBox from './CommentBox';
import CommentList from './CommentList';
import EventRSVPBtn from './EventRSVPBtn';

const EventScreen = () => (

Event name

Event description

Another description here

      <EventRSVPBtn />

        View on Meetup.com

      <CommentBox />
      <CommentList />

);

export default EventScreen;
<commit_msg>Updates to Event Screen<commit_after>import React from 'react';
import CommentBox from './CommentBox';
import CommentList from './CommentList';
import EventRSVPBtn from './EventRSVPBtn';
import { mockEvents } from '../mocks/events';

const EventScreen = ({ eventId }) => {
  const event = mockEvents[eventId];

  return (

{event.name}

        {'upcoming' === event.status && <EventRSVPBtn />}

          View on Meetup.com

        <CommentBox />
        <CommentList />

  );
};

export default EventScreen;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import {
  StyleSheet,
  ListView,
  InteractionManager
} from 'react-native';
import ListResultItem from './ListResultItem';
import InfiniteScrollView from 'react-native-infinite-scroll-view';

export default class ListResults extends Component {

  constructor(props) {
    super(props);
    this._renderCell = this._renderCell.bind(this);

    let { entries } = this.props;
    const rowHasChanged = (r1, r2) => r1 !== r2;
    let ds = new ListView.DataSource({rowHasChanged});
    this.state = {
      dataSource: ds.cloneWithRows(entries),
      canLoadMore: true
    };
  }

  _renderCell(rowData) {
    const imageAnimated = ( // Sometimes ['fixed_height_small'].url is emtpy
      rowData.images['fixed_height_small'].url == '' ?
      rowData.images['fixed_height'].url :
      rowData.images['fixed_height_small'].url
    );
    const imageStill = (
      rowData.images['fixed_height_small_still'].url == '' ?
      rowData.images['fixed_height_still'].url :
      rowData.images['fixed_height_small_still'].url
    );
    return (
      <ListResultItem still={imageStill} animated={imageAnimated} />
    )
  }

  _loadMoreAsync() {
    console.log("outside InteractionManager")
    InteractionManager.runAfterInteractions(() => {
      console.log("is loading moooore...")
    });
  }

  render() {
    return (
      <ListView
        renderScrollComponent={props => <InfiniteScrollView {...props} />}
        contentContainerStyle={styles.content}
        dataSource={this.state.dataSource}
        renderRow={this._renderCell}
        scrollRenderAheadDistance={500}
        enableEmptySections
        initialListSize={15}
        pageSize={3}
        canLoadMore={this.state.canLoadMore}
        onLoadMoreAsync={() => this._loadMoreAsync()}
      />
    )
  }
}

// ListResult.propTypes = {
//   entries: PropTypes.object,
// }

const styles = StyleSheet.create({
  content: {
    justifyContent: 'space-around',
    flexDirection: 'row',
    flexWrap: 'wrap'
  },
  item: {
    backgroundColor: 'red',
    margin: 1
  }
});<commit_msg>Removing infinite scroll<commit_after>import React, { Component } from 'react';
import {
  StyleSheet,
  ListView
} from 'react-native';
import ListResultItem from './ListResultItem';

export default class ListResults extends Component {

  constructor(props) {
    super(props);
    this._renderCell = this._renderCell.bind(this);

    let { entries } = this.props;
    const rowHasChanged = (r1, r2) => r1 !== r2;
    let ds = new ListView.DataSource({rowHasChanged});
    this.state = {
      dataSource: ds.cloneWithRows(entries),
      canLoadMore: true
    };
  }

  _renderCell(rowData) {
    const imageAnimated = ( // Sometimes ['fixed_height_small'].url is emtpy
      rowData.images['fixed_height_small'].url == '' ?
      rowData.images['fixed_height'].url :
      rowData.images['fixed_height_small'].url
    );
    const imageStill = (
      rowData.images['fixed_height_small_still'].url == '' ?
      rowData.images['fixed_height_still'].url :
      rowData.images['fixed_height_small_still'].url
    );
    return (
      <ListResultItem still={imageStill} animated={imageAnimated} />
    )
  }

  // _loadMoreAsync() { // For pagination. Not used
  //   console.log("outside InteractionManager")
  //   InteractionManager.runAfterInteractions(() => {
  //     console.log("is loading moooore...")
  //   });
  // }

  render() {
    return (
      <ListView
        contentContainerStyle={styles.content}
        dataSource={this.state.dataSource}
        renderRow={this._renderCell}
        scrollRenderAheadDistance={500}
        enableEmptySections
        initialListSize={15}
        pageSize={3}
      />
    )
  }
}

ListResults.propTypes = {
  entries: React.PropTypes.array
}

const styles = StyleSheet.create({
  content: {
    justifyContent: 'space-around',
    flexDirection: 'row',
    flexWrap: 'wrap'
  },
  item: {
    backgroundColor: 'red',
    margin: 1
  }
});<|endoftext|>


<commit_before>let traps = [];

const React = require('react');
const FocusTrap = require('focus-trap-react');

/**
 * MXFocusTrap
 *
 * Why is this needed?
 *
 * FocusTrap does not un-pause the previous trap when the current trap is unmounted.
 * This ensures that the previously trapped component is un-paused.
 */
class MXFocusTrap extends React.Component {
  state = {
    paused: false
  }

  componentWillMount () {
    // FocusTrap does it's own pausing but these React components also need to be paused
    traps.forEach(component => component.setState({ paused: true }));
    traps.push(this);
  }

  componentWillUnmount () {
    traps = traps.filter(component => component !== this);
    const lastTrap = traps[traps.length - 1];

    if (lastTrap) lastTrap.setState({ paused: false });
  }

  render () {
    return (
      <FocusTrap {...this.props} paused={this.state.paused}>
        {this.props.children}
      </FocusTrap>
    );
  }
}

/**
 * For testing purposes.  This provides an easy way to
 * unmount a child focus trap to ensure the parent is
 * unpaused. This component is only used in MXFocusTrap-test.js
 **/
class WrappedMXFocusTrap extends React.Component {
  state = {
    renderChildTrap: true
  }

  render () {
    return (
      <MXFocusTrap>
        <button>"Outer Focusable Button"</button>
        {this.state.renderChildTrap ? (
          <MXFocusTrap>
            <button>"Inner Focusable Button"</button>
          </MXFocusTrap>
        ) : null}
      </MXFocusTrap>
    );
  }
}

module.exports = {
  MXFocusTrap,
  WrappedMXFocusTrap
};<commit_msg>Removes testing component and reverts change to export<commit_after>let traps = [];

const React = require('react');
const FocusTrap = require('focus-trap-react');

/**
 * MXFocusTrap
 *
 * Why is this needed?
 *
 * FocusTrap does not un-pause the previous trap when the current trap is unmounted.
 * This ensures that the previously trapped component is un-paused.
 */
class MXFocusTrap extends React.Component {
  state = {
    paused: false
  }

  componentWillMount () {
    // FocusTrap does it's own pausing but these React components also need to be paused
    traps.forEach(component => component.setState({ paused: true }));
    traps.push(this);
  }

  componentWillUnmount () {
    traps = traps.filter(component => component !== this);
    const lastTrap = traps[traps.length - 1];

    if (lastTrap) lastTrap.setState({ paused: false });
  }

  render () {
    return (
      <FocusTrap {...this.props} paused={this.state.paused}>
        {this.props.children}
      </FocusTrap>
    );
  }
}

module.exports = MXFocusTrap;<|endoftext|>


<commit_before>import React from "react"
import _ from "lodash"

import moment from "moment"
import "moment-range"
moment.locale("ja")

import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from "recharts"

import { presetMentals } from "../Config.js"

export default function MentalChart(props) {

  const { mentals, start, end } = props

  if (!mentals) {
    return null
  }

  const days = moment.range(start, end).toArray("days")

  const d = _.map(days, d => {
    const mm = _(mentals[d.format("YYYYMMDD")]).map(m => {
      return [[m.name], parseInt(m.mental, 10)]
    }).fromPairs().value()

    return Object.assign({day: d.format("MM/DD")}, mm)
  })

  // 色はルックアップテーブルじゃなくて
  // いい感じに生成するようにしたい
  const colors = [
    "#F74123",
    "#023E7A",
    "#1DB2ED",
    "#3DBB42"
  ]

  const users = _(d)
    .flatMap(d =>  _.keys(d) )
    .reject(k => k === "day")
    .uniq()
    .value()

  const lines = users
    .map((k, i) => <Line
      key={k}
      type="monotone"
      dataKey={k}
      connectNulls={true}
      stroke={colors[i%colors.length]}
      dot={false} />)

  const tickFormatter = (a) => {
    return presetMentals[a]
  }
  const labelFormatter = (a) => {
    return presetMentals[a]
  }

  return

    <ResponsiveContainer minHeight={300} >
      <LineChart data={d}
        margin={{top: 40, right: 40, left: 0, bottom: 0}}>
        <XAxis dataKey="day" />
        <YAxis tickFormatter={tickFormatter} padding={{top:10, bottom: -55}}/>
        <CartesianGrid strokeDasharray="3 3"/>
        <Tooltip formatter={labelFormatter} />
        <Legend />
        {lines}
      </LineChart>
    </ResponsiveContainer>

}
<commit_msg>イベントを書いてるときにメンタルチャートが更新されないようにした<commit_after>import React, { Component } from "react"
import _ from "lodash"

import moment from "moment"
import "moment-range"
moment.locale("ja")

import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from "recharts"

import { presetMentals } from "../Config.js"

export default class MentalChart extends Component {

  constructor(props) {
    super(props)
  }

  shouldComponentUpdate(nextProps, nextState) {
    return _.isEqualWith(this.props, nextProps, (a, b) => {
      if (!a.start || !a.end || !a.mentals) {
        return true
      }
      return !a.start.isSame(b.start, "day")
        || !a.end.isSame(b.end, "day")
        || !_.isEqual(a.mentals, b.mentals)
    })
  }

  render() {

    const { mentals, start, end } = this.props

    if (!mentals) {
      return null
    }

    const days = moment.range(start, end).toArray("days")

    const d = _.map(days, d => {
      const mm = _(mentals[d.format("YYYYMMDD")]).map(m => {
        return [[m.name], parseInt(m.mental, 10)]
      }).fromPairs().value()

      return Object.assign({day: d.format("MM/DD")}, mm)
    })

    // 色はルックアップテーブルじゃなくて
    // いい感じに生成するようにしたい
    const colors = [
      "#F74123",
      "#023E7A",
      "#1DB2ED",
      "#3DBB42"
    ]

    const users = _(d)
      .flatMap(d =>  _.keys(d) )
      .reject(k => k === "day")
      .uniq()
      .value()

    const lines = users
      .map((k, i) => <Line
        key={k}
        type="monotone"
        dataKey={k}
        connectNulls={true}
        stroke={colors[i%colors.length]}
        dot={false} />)

    const tickFormatter = (a) => {
      return presetMentals[a]
    }
    const labelFormatter = (a) => {
      return presetMentals[a]
    }

    return

      <ResponsiveContainer minHeight={300} >
        <LineChart data={d}
          margin={{top: 40, right: 40, left: 0, bottom: 0}}>
          <XAxis dataKey="day" />
          <YAxis tickFormatter={tickFormatter} padding={{top:10, bottom: -55}}/>
          <CartesianGrid strokeDasharray="3 3"/>
          <Tooltip formatter={labelFormatter} />
          <Legend />
          {lines}
        </LineChart>
      </ResponsiveContainer>

  }
}

<|endoftext|>


<commit_before>import styled from "styled-components"
import media from "styled-media-query"

export const PostHeader = styled.header`
  max-width: 70rem;
  margin: auto;
  padding: 5rem 5rem 0;
  color: var(--postColor);

  ${media.lessThan("large")`
    padding: 3rem 0 0;
    max-width: 100%;
  `}
`

export const PostTitle = styled.h1`
  font-size: 4rem;
  font-weight: 700;
  margin: 1rem auto;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    font-size: 2.8rem;
    line-height: 1.1;
    padding: 0 1rem;
  `}
`

export const PostDescription = styled.h2`
  font-size: 2rem;
  font-weight: 200;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    font-size: 1.6rem;
    line-height: 1.3;
    padding: 0 1rem;
  `}
`

export const PostDate = styled.p`
  font-size: 1.1rem;
  font-weight: 100;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    padding: 0 1rem;
  `}
`

export const MainContent = styled.section`
  max-width: 70rem;
  margin: auto;
  padding: 2rem 5rem;

  ${media.lessThan("large")`
    padding: 2rem 0;
    max-width: 100%;
  `}

  h1,
  h2,
  h3,
  h4,
  h5 {
    margin: 2.4rem auto 1rem;
    font-weight: 800;
    letter-spacing: 0.069rem;
    line-height: 1.4;
  }

  h1 {
    font-size: 2.8rem;

    ${media.lessThan("large")`
      font-size: 1.875rem;
    `}
  }
  h2 {
    font-size: 2.1rem;

    ${media.lessThan("large")`
      font-size: 1.375rem;
    `}
  }
  h3 {
    font-size: 1.6rem;

    ${media.lessThan("large")`
      font-size: 1.125rem;
    `}
  }
  h4 {
    font-size: 1.4rem;
  }
  h5 {
    font-size: 1.2rem;
  }

  p,
  h1,
  h2,
  h3,
  h4,
  ul,
  ol,
  .tags,
  iframe,
  .button-post {
    color: var(--postColor);
    font-size: 1.25rem;
    font-weight: 300;
    line-height: 1.7;
    letter-spacing: 0.069rem;
    padding: 0 1.4rem;

    ${media.lessThan("large")`
      padding: 0 1rem;
      word-break: break-word;
    `}
  }

  p {
    margin: 0 auto 1.6rem;
  }

  ul,
  ol {
    list-style: disc;
    margin: 0 auto 1.6rem;
    padding-left: 2.5rem;
  }

  li {
    padding: 0.625rem 0;

    & > ul {
      margin-bottom: 0;
    }
  }

  p,
  li {
    code {
      word-wrap: break-word;
    }
  }

  strong {
    font-weight: 700;
  }

  blockquote {
    color: var(--postColor);
    border-left: 0.4rem solid var(--highlight);
    margin: 3rem auto;
    padding: 0 1.875rem;
  }

  hr {
    border: 1px solid var(--borders);
    margin: 3rem auto;
  }

  a {
    border-bottom: 1px dashed var(--highlight);
    color: var(--highlight);
    text-decoration: none;
    transition: opacity 0.5s;

    svg {
      color: var(--postColor);
    }

    &:hover {
      opacity: 0.8;
    }
  }

  img {
    display: block;
    max-width: 100%;
    margin: 1.875rem auto;
  }

  iframe {
    padding: 0 1.6rem 1.6rem;
    width: 100%;

    ${media.lessThan("large")`
      padding: 0 1rem;
    `}
  }

  #twitter-widget-0,
  .instagram-media,
  .twitter-tweet {
    margin: 20px auto !important;
  }

  .instagram-media {
    margin: 1rem auto !important;
  }

  .gatsby-resp-image-background-image {
    z-index: 2;
    opacity: 1 !important;
  }

  .gatsby-resp-image-image {
    box-shadow: none !important;
    transition: opacity 0.2s;

    &.lazyload {
      opacity: 0;
    }

    &.lazyloaded {
      opacity: 1;
      z-index: 3;
    }
  }

  .gatsby-highlight {
    padding: 0 1.6rem 1.6rem;

    ${media.lessThan("large")`
      padding: 0;
    `}
  }
`
<commit_msg>styled: add a new layout for iframes<commit_after>import styled from "styled-components"
import media from "styled-media-query"

export const PostHeader = styled.header`
  max-width: 70rem;
  margin: auto;
  padding: 5rem 5rem 0;
  color: var(--postColor);

  ${media.lessThan("large")`
    padding: 3rem 0 0;
    max-width: 100%;
  `}
`

export const PostTitle = styled.h1`
  font-size: 4rem;
  font-weight: 700;
  margin: 1rem auto;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    font-size: 2.8rem;
    line-height: 1.1;
    padding: 0 1rem;
  `}
`

export const PostDescription = styled.h2`
  font-size: 2rem;
  font-weight: 200;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    font-size: 1.6rem;
    line-height: 1.3;
    padding: 0 1rem;
  `}
`

export const PostDate = styled.p`
  font-size: 1.1rem;
  font-weight: 100;
  padding: 0 1.4rem;

  ${media.lessThan("large")`
    padding: 0 1rem;
  `}
`

export const MainContent = styled.section`
  max-width: 70rem;
  margin: auto;
  padding: 2rem 5rem;

  ${media.lessThan("large")`
    padding: 2rem 0;
    max-width: 100%;
  `}

  h1,
  h2,
  h3,
  h4,
  h5 {
    margin: 2.4rem auto 1rem;
    font-weight: 800;
    letter-spacing: 0.069rem;
    line-height: 1.4;
  }

  h1 {
    font-size: 2.8rem;

    ${media.lessThan("large")`
      font-size: 1.875rem;
    `}
  }
  h2 {
    font-size: 2.1rem;

    ${media.lessThan("large")`
      font-size: 1.375rem;
    `}
  }
  h3 {
    font-size: 1.6rem;

    ${media.lessThan("large")`
      font-size: 1.125rem;
    `}
  }
  h4 {
    font-size: 1.4rem;
  }
  h5 {
    font-size: 1.2rem;
  }

  p,
  h1,
  h2,
  h3,
  h4,
  ul,
  ol,
  .tags,
  iframe,
  .button-post {
    color: var(--postColor);
    font-size: 1.25rem;
    font-weight: 300;
    line-height: 1.7;
    letter-spacing: 0.069rem;
    padding: 0 1.4rem;

    ${media.lessThan("large")`
      padding: 0 1rem;
      word-break: break-word;
    `}
  }

  p {
    margin: 0 auto 1.6rem;
  }

  ul,
  ol {
    list-style: disc;
    margin: 0 auto 1.6rem;
    padding-left: 2.5rem;
  }

  li {
    padding: 0.625rem 0;

    & > ul {
      margin-bottom: 0;
    }
  }

  p,
  li {
    code {
      word-wrap: break-word;
    }
  }

  strong {
    font-weight: 700;
  }

  blockquote {
    color: var(--postColor);
    border-left: 0.4rem solid var(--highlight);
    margin: 3rem auto;
    padding: 0 1.875rem;
  }

  hr {
    border: 1px solid var(--borders);
    margin: 3rem auto;
  }

  a {
    border-bottom: 1px dashed var(--highlight);
    color: var(--highlight);
    text-decoration: none;
    transition: opacity 0.5s;

    svg {
      color: var(--postColor);
    }

    &:hover {
      opacity: 0.8;
    }
  }

  img {
    display: block;
    max-width: 100%;
    margin: 1.875rem auto;
  }

  iframe {
    padding: 0 1.6rem 1.6rem;
    width: 100%;

    ${media.lessThan("large")`
      padding: 0 1rem;
    `}
  }

  #twitter-widget-0,
  .instagram-media,
  .twitter-tweet {
    margin: 20px auto !important;
  }

  .instagram-media {
    margin: 1rem auto !important;
  }

  .gatsby-resp-image-background-image {
    z-index: 2;
    opacity: 1 !important;
  }

  .gatsby-resp-image-image {
    box-shadow: none !important;
    transition: opacity 0.2s;

    &.lazyload {
      opacity: 0;
    }

    &.lazyloaded {
      opacity: 1;
      z-index: 3;
    }
  }

  .gatsby-highlight {
    padding: 0 1.6rem 1.6rem;

    ${media.lessThan("large")`
      padding: 0;
    `}
  }

  div h2 {
    font-size: 2rem;
    font-weight: 700;
  }

  .subtitle {
    text-align: center;
    font-size: 0.8rem;
    font-family: var(--fontInter);
  }

  .videoYouTubePost {
    width: 100%;
    height: 14rem;

    ${media.greaterThan("medium")`
      height: 26rem;
    `}

    ${media.greaterThan("large")`
      height: 29rem;
    `}

    ${media.greaterThan("huge")`
      height: 34rem;
    `}
  }
`
<|endoftext|>


<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import React, {PropTypes} from 'react';
import ga from 'react-google-analytics';

import TagIcon from './tag-icon';
import MoreButton from './more-button';
import { TAG_HASHTAG, TAG_LOCATION, TAG_SCHOOL } from '../consts/tags';
import ClickOutsideComponentDecorator from '../decorators/ClickOutsideComponentDecorator';
import AddTagModal from './add-tag-modal';

@ClickOutsideComponentDecorator
export default class CreatePost extends React.Component {
  static displayName = 'CreatePost';
  static propTypes = {
    actions: PropTypes.shape({
      resetCreatePostForm: PropTypes.func,
      updateCreatePostForm: PropTypes.func
    }),
    allSchools: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    defaultText: PropTypes.string,
    geotags: PropTypes.arrayOf(PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string
    })),
    schools: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    hashtags: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    triggers: PropTypes.shape({
      createPost: PropTypes.func.isRequired
    })
  };

  state = {
    expanded: false,
    addTagModalType: null
  };

  _stopPropagation = (e) => {
    if (e) {
      e.stopPropagation();
      e.nativeEvent.stopImmediatePropagation();
    }
  };

  onClickOutside = () => {
    let form = this.refs.form;

    if (!form.text.value.trim().length) {
      this.setState({
        expanded: false
      });
    }
  };

  _handleSubmit = async (event) => {
    event.preventDefault();

    let form = this.refs.form;

    if (!form.text.value.trim().length) {
      return;
    }

    let data = {
      text: form.text.value,
      hashtags: this.props.hashtags.map(hashtag => hashtag.name),
      schools: this.props.schools.map(school => school.name),
      geotags: this.props.geotags.map(geotag => geotag.id),
      minor_update: form.minor_update.checked
    };

    this.props.actions.resetCreatePostForm();

    await this.props.triggers.createPost('short_text', data);
    ga('send', 'event', 'Post', 'Done', data.hashtags.join(','));

    form.text.value = '';
    this._addTagModal.reset();
  };

  _handleFocus = () => {
    this.setState({
      expanded: true
    });
  };

  _handleClickOnMore = () => {
    this.setState({
      expanded: !this.state.expanded
    });
  };

  _showAddHashtagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_HASHTAG
    });
  };

  _showAddSchoolModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_SCHOOL
    });
  };

  _showAddGeotagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_LOCATION
    });
  };

  _closeAddTagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: null
    });
  };

  _changeAddTagModal = (newType) => {
    this.setState({
      addTagModalType: newType
    })
  };

  /**
   * @param {Object} tags - {hashtags: [], schools: [], geotags: [], ...}
   */
  _addTags = (tags) => {
    this.props.actions.updateCreatePostForm(tags);

    this._closeAddTagModal();
  };

  render () {
    let {
      addTagModalType,
      expanded
    } = this.state;

    return (

        <form ref="form" onSubmit={this._handleSubmit}>

                  {!expanded &&

                  }
                  <textarea
                    className="input input-block create_post__text_input"
                    defaultValue={this.props.defaultText}
                    name="text"
                    placeholder="Make a contribution to education change"
                    rows={(this.state.expanded) ? 10 : 1}
                    onFocus={this._handleFocus}
                  />

                <MoreButton expanded={expanded} onClick={this._handleClickOnMore} />
                {expanded &&

                    <TagIcon className="create_post__tag_button" type={TAG_SCHOOL} onClick={this._showAddSchoolModal} />
                    <TagIcon className="create_post__tag_button" type={TAG_LOCATION} onClick={this._showAddGeotagModal}  />
                    {/*<TagIcon className="create_post__tag_button" type={TAG_EVENT} />*/}
                    {/*<TagIcon className="create_post__tag_button" type={TAG_MENTION} />*/}
                    <TagIcon className="create_post__tag_button" type={TAG_HASHTAG} onClick={this._showAddHashtagModal} />

                }

            {expanded &&

                  <button className="button button-wide button-red" type="submit">Publish</button>

                  {/*<button className="button button-wide button-transparent" type="button">Go full screen</button>*/}

                    Minor update (?)
                    <input name="minor_update" type="checkbox" />

            }

        </form>
        <AddTagModal
          allSchools={this.props.allSchools}
          geotags={this.props.geotags}
          hashtags={this.props.hashtags}
          ref={(c) => this._addTagModal = c}
          schools={this.props.schools}
          type={addTagModalType}
          onClose={this._closeAddTagModal}
          onSave={this._addTags}
          onTypeChange={this._changeAddTagModal}
        />

    )
  }
}
<commit_msg>Ctrl+Enter publish for making posts<commit_after>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import React, {PropTypes} from 'react';
import ga from 'react-google-analytics';

import TagIcon from './tag-icon';
import MoreButton from './more-button';
import { TAG_HASHTAG, TAG_LOCATION, TAG_SCHOOL } from '../consts/tags';
import ClickOutsideComponentDecorator from '../decorators/ClickOutsideComponentDecorator';
import AddTagModal from './add-tag-modal';

@ClickOutsideComponentDecorator
export default class CreatePost extends React.Component {
  static displayName = 'CreatePost';
  static propTypes = {
    actions: PropTypes.shape({
      resetCreatePostForm: PropTypes.func,
      updateCreatePostForm: PropTypes.func
    }),
    allSchools: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    defaultText: PropTypes.string,
    geotags: PropTypes.arrayOf(PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string
    })),
    schools: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    hashtags: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string
    })),
    triggers: PropTypes.shape({
      createPost: PropTypes.func.isRequired
    })
  };

  state = {
    expanded: false,
    addTagModalType: null
  };

  _stopPropagation = (e) => {
    if (e) {
      e.stopPropagation();
      e.nativeEvent.stopImmediatePropagation();
    }
  };

  onClickOutside = () => {
    let form = this.refs.form;

    if (!form.text.value.trim().length) {
      this.setState({
        expanded: false
      });
    }
  };

  _handleSubmit = async (event) => {
    event.preventDefault();

    let form = this.refs.form;

    if (!form.text.value.trim().length) {
      return;
    }

    let data = {
      text: form.text.value,
      hashtags: this.props.hashtags.map(hashtag => hashtag.name),
      schools: this.props.schools.map(school => school.name),
      geotags: this.props.geotags.map(geotag => geotag.id),
      minor_update: form.minor_update.checked
    };

    this.props.actions.resetCreatePostForm();

    await this.props.triggers.createPost('short_text', data);
    ga('send', 'event', 'Post', 'Done', data.hashtags.join(','));

    form.text.value = '';
    this._addTagModal.reset();
  };

  _handleFocus = () => {
    this.setState({
      expanded: true
    });
  };

  _handleClickOnMore = () => {
    this.setState({
      expanded: !this.state.expanded
    });
  };

  _handleKeydown = (e) => {
    const ENTER = 13;

    if (e.ctrlKey || e.metaKey) {
      if (e.keyCode === ENTER) {
        const submit = new Event('submit');
        this.refs.form.dispatchEvent(submit);
      }
    }
  };

  _showAddHashtagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_HASHTAG
    });
  };

  _showAddSchoolModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_SCHOOL
    });
  };

  _showAddGeotagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: TAG_LOCATION
    });
  };

  _closeAddTagModal = (e) => {
    this._stopPropagation(e);

    this.setState({
      addTagModalType: null
    });
  };

  _changeAddTagModal = (newType) => {
    this.setState({
      addTagModalType: newType
    })
  };

  /**
   * @param {Object} tags - {hashtags: [], schools: [], geotags: [], ...}
   */
  _addTags = (tags) => {
    this.props.actions.updateCreatePostForm(tags);

    this._closeAddTagModal();
  };

  render () {
    let {
      addTagModalType,
      expanded
    } = this.state;

    return (

        <form ref="form" onSubmit={this._handleSubmit} onKeyDown={this._handleKeydown}>

                  {!expanded &&

                  }
                  <textarea
                    className="input input-block create_post__text_input"
                    defaultValue={this.props.defaultText}
                    name="text"
                    placeholder="Make a contribution to education change"
                    rows={(this.state.expanded) ? 10 : 1}
                    onFocus={this._handleFocus}
                  />

                <MoreButton expanded={expanded} onClick={this._handleClickOnMore} />
                {expanded &&

                    <TagIcon className="create_post__tag_button" type={TAG_SCHOOL} onClick={this._showAddSchoolModal} />
                    <TagIcon className="create_post__tag_button" type={TAG_LOCATION} onClick={this._showAddGeotagModal}  />
                    {/*<TagIcon className="create_post__tag_button" type={TAG_EVENT} />*/}
                    {/*<TagIcon className="create_post__tag_button" type={TAG_MENTION} />*/}
                    <TagIcon className="create_post__tag_button" type={TAG_HASHTAG} onClick={this._showAddHashtagModal} />

                }

            {expanded &&

                  <button className="button button-wide button-red" type="submit">Publish</button>

                  {/*<button className="button button-wide button-transparent" type="button">Go full screen</button>*/}

                    Minor update (?)
                    <input name="minor_update" type="checkbox" />

            }

        </form>
        <AddTagModal
          allSchools={this.props.allSchools}
          geotags={this.props.geotags}
          hashtags={this.props.hashtags}
          ref={(c) => this._addTagModal = c}
          schools={this.props.schools}
          type={addTagModalType}
          onClose={this._closeAddTagModal}
          onSave={this._addTags}
          onTypeChange={this._changeAddTagModal}
        />

    )
  }
}
<|endoftext|>